Import DAHDI-Tools r9159
[dahdi/tools.git] / fxstest.c
1 /*
2  * Written by Mark Spencer <markster@digium.com>
3  * Based on previous works, designs, and architectures conceived and
4  * written by Jim Dixon <jim@lambdatel.com>.
5  *
6  * Copyright (C) 2001 Jim Dixon / Zapata Telephony.
7  * Copyright (C) 2001-2008 Digium, Inc.
8  *
9  * All rights reserved.
10  *
11  * Primary Author: Mark Spencer <markster@digium.com>
12  * Radio Support by Jim Dixon <jim@lambdatel.com>
13  */
14
15 /*
16  * See http://www.asterisk.org for more information about
17  * the Asterisk project. Please do not directly contact
18  * any of the maintainers of this project for assistance;
19  * the project provides a web site, mailing lists and IRC
20  * channels for your use.
21  *
22  * This program is free software, distributed under the terms of
23  * the GNU General Public License Version 2 as published by the
24  * Free Software Foundation. See the LICENSE file included with
25  * this program for more details.
26  */
27
28 #include <stdio.h>
29 #include <string.h>
30 #include <ctype.h>
31 #include <errno.h>
32 #include <fcntl.h>
33 #include <stdlib.h>
34 #include <unistd.h>
35 #include <sys/ioctl.h>
36 #include <dahdi/user.h>
37 #include <dahdi/wctdm_user.h>
38
39 #include "tonezone.h"
40 #include "dahdi_tools_version.h"
41
42 static int tones[] = {
43         DAHDI_TONE_DIALTONE,
44         DAHDI_TONE_BUSY,
45         DAHDI_TONE_RINGTONE,
46         DAHDI_TONE_CONGESTION,
47         DAHDI_TONE_DIALRECALL,
48 };
49
50 struct dahdi_vmwi_info mwisend_setting; /*!< Which VMWI methods to use */
51
52 /* Use to translate a DTMF character to the value required by the dahdi call */
53 static int digit_to_dtmfindex(char digit)
54 {
55         if (isdigit(digit))
56                 return DAHDI_TONE_DTMF_BASE + (digit - '0');
57         else if (digit >= 'A' && digit <= 'D')
58                 return DAHDI_TONE_DTMF_A + (digit - 'A');
59         else if (digit >= 'a' && digit <= 'd')
60                 return DAHDI_TONE_DTMF_A + (digit - 'a');
61         else if (digit == '*')
62                 return DAHDI_TONE_DTMF_s;
63         else if (digit == '#')
64                 return DAHDI_TONE_DTMF_p;
65         else
66                 return -1;
67 }
68
69 /* Place a channel into ringing mode */
70 static int dahdi_ring_phone(int fd)
71 {
72         int x;
73         int res;
74         /* Make sure our transmit state is on hook */
75         x = 0;
76         x = DAHDI_ONHOOK;
77         res = ioctl(fd, DAHDI_HOOK, &x);
78         do {
79                 x = DAHDI_RING;
80                 res = ioctl(fd, DAHDI_HOOK, &x);
81                 if (res) {
82                         switch (errno) {
83                                 case EBUSY:
84                                 case EINTR:
85                                         /* Wait just in case */
86                                         fprintf(stderr, "Ring phone is busy:%s\n", strerror(errno));
87                                         usleep(10000);
88                                         continue;
89                                 case EINPROGRESS:
90                                         fprintf(stderr, "Ring In Progress:%s\n", strerror(errno));
91                                         res = 0;
92                                         break;
93                                 default:
94                                         fprintf(stderr, "Couldn't ring the phone: %s\n", strerror(errno));
95                                         res = 0;
96                         }
97                 } else {
98                         fprintf(stderr, "Phone is ringing\n");
99                 }
100         } while (res);
101         return res;
102 }
103
104 int main(int argc, char *argv[])
105 {
106         int fd;
107         int res;
108         int x;
109         if (argc < 3) {
110                 fprintf(stderr, "Usage: fxstest <dahdi device> <cmd>\n"
111                        "       where cmd is one of:\n"
112                        "       stats - reports voltages\n"
113                        "       regdump - dumps ProSLIC registers\n"
114                        "       tones - plays a series of tones\n"
115                        "       polarity - tests polarity reversal\n"
116                        "       ring - rings phone\n"
117                        "       vmwi - toggles VMWI LED lamp\n"
118                        "       hvdc - toggles VMWI HV lamp\n"
119                        "       neon - toggles VMWI NEON lamp\n"
120                        "       dtmf <sequence> [<duration>]- Send a sequence of dtmf tones (\"-\" denotes no tone)\n"
121                        "       dtmfcid - create a dtmf cid spill without polarity reversal\n");
122                 exit(1);
123         }
124         fd = open(argv[1], O_RDWR);
125         if (fd < 0) {
126                 fprintf(stderr, "Unable to open %s: %s\n", argv[1], strerror(errno));
127                 exit(1);
128         }
129         
130         if ( !strcasecmp(argv[2], "neon") || !strcasecmp(argv[2], "vmwi") || !strcasecmp(argv[2], "hvdc")) {
131                 fprintf(stderr, "Twiddling %s ...\n", argv[2]);
132
133                 if ( !strcasecmp(argv[2], "vmwi") ) {
134                         mwisend_setting.vmwi_type = DAHDI_VMWI_LREV;
135                 } else if ( !strcasecmp(argv[2], "neon") ) {
136                         mwisend_setting.vmwi_type = DAHDI_VMWI_HVAC;
137                 } else if ( !strcasecmp(argv[2], "hvdc") ) {
138                         mwisend_setting.vmwi_type = DAHDI_VMWI_HVDC;
139                 }
140                 res = ioctl(fd, DAHDI_VMWI_CONFIG, &mwisend_setting);
141
142                 x = 1;
143                 res = ioctl(fd, DAHDI_VMWI, &x);
144                 if (res) {
145                         fprintf(stderr, "Unable to set %s ...\n", argv[2]);
146                 } else {
147                         fprintf(stderr, "Set 1 Voice Message...\n");
148
149                         sleep(5);
150                         x = 2;
151                         ioctl(fd, DAHDI_VMWI, &x);
152                         fprintf(stderr, "Set 2 Voice Messages...\n");
153
154                         sleep(5);
155                         x = 0;
156                         ioctl(fd, DAHDI_VMWI, &x);
157                         fprintf(stderr, "Set No Voice messages...\n");
158                         sleep(2);
159                         mwisend_setting.vmwi_type = 0;
160                 }
161         } else if (!strcasecmp(argv[2], "ring")) {
162                 fprintf(stderr, "Ringing phone...\n");
163                 x = DAHDI_RING;
164                 res = ioctl(fd, DAHDI_HOOK, &x);
165                 if (res) {
166                         fprintf(stderr, "Unable to ring phone...\n");
167                 } else {
168                         fprintf(stderr, "Phone is ringing...\n");
169                         sleep(2);
170                 }
171         } else if (!strcasecmp(argv[2], "polarity")) {
172                 fprintf(stderr, "Twiddling polarity...\n");
173                 /* Insure that the channel is in active mode */
174                 x = DAHDI_RING;
175                 res = ioctl(fd, DAHDI_HOOK, &x);
176                 usleep(100000);
177                 x = 0;
178                 res = ioctl(fd, DAHDI_HOOK, &x);
179
180                 x = 0;
181                 res = ioctl(fd, DAHDI_SETPOLARITY, &x);
182                 if (res) {
183                         fprintf(stderr, "Unable to polarity...\n");
184                 } else {
185                         fprintf(stderr, "Polarity is forward...\n");
186                         sleep(2);
187                         x = 1;
188                         ioctl(fd, DAHDI_SETPOLARITY, &x);
189                         fprintf(stderr, "Polarity is reversed...\n");
190                         sleep(5);
191                         x = 0;
192                         ioctl(fd, DAHDI_SETPOLARITY, &x);
193                         fprintf(stderr, "Polarity is forward...\n");
194                         sleep(2);
195                 }
196         } else if (!strcasecmp(argv[2], "tones")) {
197                 int x = 0;
198                 for (;;) {
199                         res = tone_zone_play_tone(fd, tones[x]);
200                         if (res)
201                                 fprintf(stderr, "Unable to play tone %d\n", tones[x]);
202                         sleep(3);
203                         x=(x+1) % (sizeof(tones) / sizeof(tones[0]));
204                 }
205         } else if (!strcasecmp(argv[2], "stats")) {
206                 struct wctdm_stats stats;
207                 res = ioctl(fd, WCTDM_GET_STATS, &stats);
208                 if (res) {
209                         fprintf(stderr, "Unable to get stats on channel %s\n", argv[1]);
210                 } else {
211                         printf("TIP: %7.4f Volts\n", (float)stats.tipvolt / 1000.0);
212                         printf("RING: %7.4f Volts\n", (float)stats.ringvolt / 1000.0);
213                         printf("VBAT: %7.4f Volts\n", (float)stats.batvolt / 1000.0);
214                 }
215         } else if (!strcasecmp(argv[2], "regdump")) {
216                 struct wctdm_regs regs;
217                 int numregs = NUM_REGS;
218                 memset(&regs, 0, sizeof(regs));
219                 res = ioctl(fd, WCTDM_GET_REGS, &regs);
220                 if (res) {
221                         fprintf(stderr, "Unable to get registers on channel %s\n", argv[1]);
222                 } else {
223                         for (x=60;x<NUM_REGS;x++) {
224                                 if (regs.direct[x])
225                                         break;
226                         }
227                         if (x == NUM_REGS) 
228                                 numregs = 60;
229                         printf("Direct registers: \n");
230                         for (x=0;x<numregs;x++) {
231                                 printf("%3d. %02x  ", x, regs.direct[x]);
232                                 if ((x % 8) == 7)
233                                         printf("\n");
234                         }
235                         if (numregs == NUM_REGS) {
236                                 printf("\n\nIndirect registers: \n");
237                                 for (x=0;x<NUM_INDIRECT_REGS;x++) {
238                                         printf("%3d. %04x  ", x, regs.indirect[x]);
239                                         if ((x % 6) == 5)
240                                                 printf("\n");
241                                 }
242                         }
243                         printf("\n\n");
244                 }
245         } else if (!strcasecmp(argv[2], "setdirect") ||
246                                 !strcasecmp(argv[2], "setindirect")) {
247                 struct wctdm_regop regop;
248                 int val;
249                 int reg;
250                 if ((argc < 5) || (sscanf(argv[3], "%i", &reg) != 1) ||
251                         (sscanf(argv[4], "%i", &val) != 1)) {
252                         fprintf(stderr, "Need a register and value...\n");
253                 } else {
254                         regop.reg = reg;
255                         regop.val = val;
256                         if (!strcasecmp(argv[2], "setindirect")) {
257                                 regop.indirect = 1;
258                         } else {
259                                 regop.indirect = 0;
260                         }
261                         res = ioctl(fd, WCTDM_SET_REG, &regop);
262                         if (res) 
263                                 fprintf(stderr, "Unable to get registers on channel %s\n", argv[1]);
264                         else
265                                 printf("Success.\n");
266                 }
267         } else if (!strcasecmp(argv[2], "dtmf")) {
268                 int duration = 50;  /* default to 50 mS duration */
269                 char * outstring = "";
270                 int dtmftone;
271
272                 if(argc < 4) {  /* user supplied string */
273                         fprintf(stderr, "You must specify a string of dtmf characters to send\n");
274                 } else {
275                         outstring = argv[3];
276                         if(argc >= 5) {
277                                 sscanf(argv[4], "%30i", &duration);
278                         }
279                         printf("Going to send a set of DTMF tones >%s<\n", outstring);
280                         printf("Using a duration of %d mS per tone\n", duration);
281                                         /* Flush any left remaining characs in the buffer and place the channel into on-hook transfer mode */
282                         x = DAHDI_FLUSH_BOTH;
283                         res = ioctl(fd, DAHDI_FLUSH, &x);
284                         x = 500 + strlen(outstring) * duration;
285                         ioctl(fd, DAHDI_ONHOOKTRANSFER, &x);
286
287                         for (x = 0; '\0' != outstring[x]; x++) {
288                                 dtmftone = digit_to_dtmfindex(outstring[x]);
289                                 if (0 > dtmftone) {
290                                         dtmftone = -1;
291                                 }
292                                 res = tone_zone_play_tone(fd, dtmftone);
293                                 if (res) {
294                                         fprintf(stderr, "Unable to play DTMF tone %d (0x%x)\n", dtmftone, dtmftone);
295                                 }
296                                 usleep(duration * 1000);
297                         }
298                 }
299         } else if (!strcasecmp(argv[2], "dtmfcid")) {
300                 char * outstring = "A5551212C";  /* Default string using A and C tones to bracket the number */
301                 int dtmftone;
302                 
303                 if(argc >= 4) { /* Use user supplied string */
304                         outstring = argv[3];
305                 }
306                 printf("Going to send a set of DTMF tones >%s<\n", outstring);
307                 /* Flush any left remaining characs in the buffer and place the channel into on-hook transfer mode */
308                 x = DAHDI_FLUSH_BOTH;
309                 res = ioctl(fd, DAHDI_FLUSH, &x);
310                 x = 500 + strlen(outstring) * 100;
311                 ioctl(fd, DAHDI_ONHOOKTRANSFER, &x);
312
313                 /* Play the DTMF tones at a 50 mS on and 50 mS off rate which is standard for DTMF CID spills */
314                 for (x = 0; '\0' != outstring[x]; x++) {
315
316                         dtmftone = digit_to_dtmfindex(outstring[x]);
317                         if (0 > dtmftone) {
318                                 dtmftone = -1;
319                         }
320                         res = tone_zone_play_tone(fd, dtmftone);
321                         if (res) {
322                                 fprintf(stderr, "Unable to play DTMF tone %d (0x%x)\n", dtmftone, dtmftone);
323                         }
324                         usleep(50000);
325                         tone_zone_play_tone(fd, -1);
326                         usleep(50000);
327                 }
328                 /* Wait for 150 mS from end of last tone to initiating the ring */
329                 usleep(100000);
330                 dahdi_ring_phone(fd);
331                 sleep(10);
332                 printf("Ringing Done\n");
333         } else
334                 fprintf(stderr, "Invalid command\n");
335         close(fd);
336         return 0;
337 }