Compare commits

...

29 Commits

Author SHA1 Message Date
Shaun Ruffell
b18877c4ab Use autotagged externals
git-svn-id: http://svn.astersk.org/svn/dahdi/tools/tags/2.6.0@10403 17933a7a-c749-41c5-a318-cba88f637d49
2012-01-03 23:19:09 +00:00
Shaun Ruffell
6d945a01c3 Importing files for 2.6.0 release.
git-svn-id: http://svn.astersk.org/svn/dahdi/tools/tags/2.6.0@10402 17933a7a-c749-41c5-a318-cba88f637d49
2012-01-03 23:18:58 +00:00
Shaun Ruffell
74a791799e Creating tag for the release of dahdi-tools-2.6.0
git-svn-id: http://svn.astersk.org/svn/dahdi/tools/tags/2.6.0@10401 17933a7a-c749-41c5-a318-cba88f637d49
2012-01-03 23:18:23 +00:00
Tzafrir Cohen
dfa7a08ba3 xpp: two extra product IDs: 1112, 1164
Two extra USB product IDs used in some odd maintenance scenarios.

Signed-off-by: Tzafrir Cohen <tzafrir.cohen@xorcom.com>

git-svn-id: http://svn.astersk.org/svn/dahdi/tools/trunk@10368 17933a7a-c749-41c5-a318-cba88f637d49
2011-12-04 17:08:29 +00:00
Tzafrir Cohen
32b715d373 xpp: xpp_fxloader: regressions from r10348
* Avoid a duplicated run of udev on some systems.
* Fix usage of astribank_tool's output.

Signed-off-by: Tzafrir Cohen <tzafrir.cohen@xorcom.com>

git-svn-id: http://svn.astersk.org/svn/dahdi/tools/trunk@10366 17933a7a-c749-41c5-a318-cba88f637d49
2011-12-04 15:33:21 +00:00
Tzafrir Cohen
03c0afef41 DAHDI-perl: Fix PCI ID for Rhino R4T1 (0b0b:0305)
(Closes issue DAHTOOL-56)

Signed-off-by: Tzafrir Cohen <tzafrir.cohen@xorcom.com>

git-svn-id: http://svn.astersk.org/svn/dahdi/tools/trunk@10358 17933a7a-c749-41c5-a318-cba88f637d49
2011-11-30 20:15:33 +00:00
Tzafrir Cohen
1b9a64e43b xpp: recovery firmware in xpp_fxloader
USB_RECOV.hex is an extra firmware that may be useful for recovering
from certain Astribank hardware faults in some scenarios. This adds
support for either loading it manually
('/usr/share/dahdi/xpp_fxloader recover-sb') or through udev, *if*
the required udev rules were set on the system.

Signed-off-by: Tzafrir Cohen <tzafrir.cohen@xorcom.com>

git-svn-id: http://svn.astersk.org/svn/dahdi/tools/trunk@10349 17933a7a-c749-41c5-a318-cba88f637d49
2011-11-29 23:40:50 +00:00
Tzafrir Cohen
e6c2b1850d xpp: Serialized Parallel load; E-Main-3 firmware
This introduces support for loading multiple firmwares in parallel also
for the case of a manual load. This is anyway the case for an automatic
load from udev.

* libusb needs to scan the bus all too often. This causes occasional
  failures for opening devices.
* Thus introduce a semaphore to serialize uses of libusb.

E-Main-3 firmware differs by a different value of bcdDevice:

* Read this from the sysfs devices tree.
* Fall back to lsusb -v (much slower) is sysfs not available.

Signed-off-by: Tzafrir Cohen <tzafrir.cohen@xorcom.com>

git-svn-id: http://svn.astersk.org/svn/dahdi/tools/trunk@10348 17933a7a-c749-41c5-a318-cba88f637d49
2011-11-29 23:40:21 +00:00
Tzafrir Cohen
29280a548c xpp: astribank_hexload: we need more lines
* Newer firmwares may have more lines.
* While we're at it, add better debug printing.
* Remove some unused debugging code.

Signed-off-by: Tzafrir Cohen <tzafrir.cohen@xorcom.com>

git-svn-id: http://svn.astersk.org/svn/dahdi/tools/trunk@10343 17933a7a-c749-41c5-a318-cba88f637d49
2011-11-21 15:25:43 +00:00
Tzafrir Cohen
b093554f54 Fix GCC 4.6 "set but not used" warnings
Signed-off-by: Tzafrir Cohen <tzafrir.cohen@xorcom.com>

git-svn-id: http://svn.astersk.org/svn/dahdi/tools/trunk@10311 17933a7a-c749-41c5-a318-cba88f637d49
2011-11-02 21:57:25 +00:00
Shaun Ruffell
bc6250fe1f dahdi_genconf: Allow it to recognize the TE8xx 8-port cards.
Signed-off-by: Shaun Ruffell <sruffell@digium.com>

git-svn-id: http://svn.astersk.org/svn/dahdi/tools/trunk@10308 17933a7a-c749-41c5-a318-cba88f637d49
2011-11-02 20:55:52 +00:00
Oron Peled
ba070152fc dahdi_cfg: add '-S <spanno>' and '-C <chan-ranges>'
* dahdi_cfg -S <num>: only apply changes to span <num>.
* If span is analog (no 'span=<num>,<channels>,...' statement in
  system.conf), we need to set range: -C <channels>
* With the <basechan> and <channels> attributes in sysfs
  we easily configure each device on the fly.
  Simply run: dahdi_cfg -S <spanno> -C <basechan>+<channels>-1
  from udev script

Signed-off-by: Oron Peled <oron.peled@xorcom.com>
Acked-by: Tzafrir Cohen <tzafrir.cohen@xorcom.com>

git-svn-id: http://svn.astersk.org/svn/dahdi/tools/trunk@10306 17933a7a-c749-41c5-a318-cba88f637d49
2011-11-02 20:10:06 +00:00
Torrey Searle
541435eac7 dahdi_pcap: Imported user space utility for managing pcap streams
This utility will export packet captures for channels in dahdi. It requires
CONFIG_DAHDI_MIRROR to be defined in dahdi-linux as it uses the unsupported
DAHDI_MIRROR ioctl interface.

Internal-Issue-ID: DAHTOOL-49
From: Torrey Searle <tsearle@gmail.com>
Signed-off-by: Russ Meyerriecks <rmeyerriecks@digium.com>
Acked-by: Shaun Ruffell <sruffell@digium.com>

git-svn-id: http://svn.astersk.org/svn/dahdi/tools/trunk@10293 17933a7a-c749-41c5-a318-cba88f637d49
2011-11-01 18:10:14 +00:00
Tzafrir Cohen
2457399d92 dahdi_perl: Use $Dahdi::sys_base for sysfs pathes
Signed-off-by: Tzafrir Cohen <tzafrir.cohen@xorcom.com>

git-svn-id: http://svn.astersk.org/svn/dahdi/tools/trunk@10267 17933a7a-c749-41c5-a318-cba88f637d49
2011-10-23 14:43:27 +00:00
Tzafrir Cohen
a81a43c9b6 xpp_order generator: ignore EC XPD
The xpp_order configuration generator should only loop over telephony
devices, not all spans.

Signed-off-by: Tzafrir Cohen <tzafrir.cohen@xorcom.com>

git-svn-id: http://svn.astersk.org/svn/dahdi/tools/trunk@10266 17933a7a-c749-41c5-a318-cba88f637d49
2011-10-23 14:28:40 +00:00
Tzafrir Cohen
5efd590aef chandahdi gen: extens can have any num of digits
Don't force extens we generate to have exactly 4 digits (simple
formatting limitation).

Signed-off-by: Tzafrir Cohen <tzafrir.cohen@xorcom.com>

git-svn-id: http://svn.astersk.org/svn/dahdi/tools/trunk@10265 17933a7a-c749-41c5-a318-cba88f637d49
2011-10-23 14:23:17 +00:00
Tzafrir Cohen
1e21cb1356 Typos in man pages: toolyou
Signed-off-by: Tzafrir Cohen <tzafrir.cohen@xorcom.com>

git-svn-id: http://svn.astersk.org/svn/dahdi/tools/trunk@10264 17933a7a-c749-41c5-a318-cba88f637d49
2011-10-23 14:22:05 +00:00
Shaun Ruffell
78584da122 dahdi_test: Enforce range from 0.0% - 100.0% for accuracy.
Also makes sure that the percentage output from the verbose and
non-verbose modes of timer_test are the same and print a cumulative
accuracy which smooths out the jitter for each pass.

If the time it takes to read in 1 second worth of data is longer than 1
second  accuracy will be 0%.

(closes issue #18573)
Reported by: smurfix

Signed-off-by: Shaun Ruffell <sruffell@digium.com>

git-svn-id: http://svn.astersk.org/svn/dahdi/tools/trunk@10216 17933a7a-c749-41c5-a318-cba88f637d49
2011-09-29 17:00:59 +00:00
Shaun Ruffell
cbb0252a6a dahdi_maint: Print 'unsupported' warning if framing errors is -1.
Warn the user if attempting to monitor a statistic that the particular
board driver does not appear to be collecting. The wcte12xp in r10212 in
now fills in -1 for any statistic it does not collect and other digital
cards can do the same.

Signed-off-by: Shaun Ruffell <sruffell@digium.com>
Acked-by: Russ Meyerriecks <rmeyerriecks@digium.com>

git-svn-id: http://svn.astersk.org/svn/dahdi/tools/trunk@10215 17933a7a-c749-41c5-a318-cba88f637d49
2011-09-29 17:00:55 +00:00
Shaun Ruffell
250bc06238 dahdi_genconf: Use 'dahdi_scan' to determine span_type for B410P cards.
The wcb4xxp driver does not put enough information in the proc filesystem to
determine if the ports are in TE or NT mode.  Previously the ports would
always just setup the dahdi-channels.conf file in TE mode. After this change
the dahdi_scan utility is used to detect if the ports are in TE or NT mode and
setup dahdi-channels.conf appropriately.

Internal-Issue-ID: DAHTOOL-54
Signed-off-by: Shaun Ruffell <sruffell@digium.com>

git-svn-id: http://svn.astersk.org/svn/dahdi/tools/trunk@10214 17933a7a-c749-41c5-a318-cba88f637d49
2011-09-29 17:00:51 +00:00
Shaun Ruffell
db9b649e03 dahdi_genconf: Assume spans with unknown term types are software selectable.
Resolves a regression on the 2.5 branch that would result in:

  $ dahdi_genconf
  dahdi_genconf: missing default group (termtype=UNKNOWN)

E1 / T1 spans use software configuration to set CPE / NET mode. This
patch will just assume that a termtype is software selectable if it was
"UNKNOWN" when first scanning the span.

Internal-Issue-ID: DAHTOOL-55
Signed-off-by: Shaun Ruffell <sruffell@digium.com>
Tested-by: David Purdue <support@noojee.com.au>

git-svn-id: http://svn.astersk.org/svn/dahdi/tools/trunk@10213 17933a7a-c749-41c5-a318-cba88f637d49
2011-09-29 17:00:46 +00:00
Tzafrir Cohen
2d576dcea0 Man page for dahdi_maint
Fix dahdi_maint's usage message while we're at it.

Signed-off-by: Tzafrir Cohen <tzafrir.cohen@xorcom.com>

git-svn-id: http://svn.astersk.org/svn/dahdi/tools/trunk@10198 17933a7a-c749-41c5-a318-cba88f637d49
2011-09-09 13:45:00 +00:00
Tzafrir Cohen
b487a96ada Update the dahdi-monitor man page
Signed-off-by: Tzafrir Cohen <tzafrir.cohen@xorcom.com>

git-svn-id: http://svn.astersk.org/svn/dahdi/tools/trunk@10196 17933a7a-c749-41c5-a318-cba88f637d49
2011-09-09 12:04:34 +00:00
Tzafrir Cohen
67cc13f100 fix typos in some xpp utils
Signed-off-by: Tzafrir Cohen <tzafrir.cohen@xorcom.com>

git-svn-id: http://svn.astersk.org/svn/dahdi/tools/trunk@10194 17933a7a-c749-41c5-a318-cba88f637d49
2011-09-09 10:59:39 +00:00
Tzafrir Cohen
3482a25b84 xpp: waitfor_xpds: higher and configurable timeout
On several pathological cases we may need to wait more than 40 seconds.
Make that timeout configurable.

git-svn-id: http://svn.astersk.org/svn/dahdi/tools/trunk@10177 17933a7a-c749-41c5-a318-cba88f637d49
2011-09-05 09:05:48 +00:00
Oron Peled
b23f3ca5a9 dahdi-perl: Also get USB loaded driver from usbfs
Signed-off-by: Oron Peled <oron.peled@xorcom.com>
Signed-off-by: Tzafrir Cohen <tzafrir.cohen@xorcom.com>

git-svn-id: http://svn.astersk.org/svn/dahdi/tools/trunk@10153 17933a7a-c749-41c5-a318-cba88f637d49
2011-08-25 10:32:17 +00:00
Tzafrir Cohen
a5c6e58b6e dahdi-perl: Freepbxdb config generator
Use 'dahdi_genconf freepbxdb' to generate the required astdb entries
for Asterisk to use the extensions generated by dahdi_genconf. Requires
asterisk to be running.

This module is intended for testing as it bypasses standard FreePBX
functions only and hence may not work properly with Freepbx.

Signed-off-by: Tzafrir Cohen <tzafrir.cohen@xorcom.com>

git-svn-id: http://svn.astersk.org/svn/dahdi/tools/trunk@10142 17933a7a-c749-41c5-a318-cba88f637d49
2011-08-18 15:38:45 +00:00
Tzafrir Cohen
12492f4e23 README.Astribank: HWEC and build instructions
Signed-off-by: Tzafrir Cohen <tzafrir.cohen@xorcom.com>

git-svn-id: http://svn.astersk.org/svn/dahdi/tools/trunk@10104 17933a7a-c749-41c5-a318-cba88f637d49
2011-08-10 15:31:22 +00:00
Tzafrir Cohen
2061c6c359 xpp: pri_termtype: match complete SPAN patterns
Match complete span patterns, to avoid pattern 'SPAN/1' from matching
e.g. span 12 (SPAN/12).

Signed-off-by: Tzafrir Cohen <tzafrir.cohen@xorcom.com>

git-svn-id: http://svn.astersk.org/svn/dahdi/tools/trunk@10101 17933a7a-c749-41c5-a318-cba88f637d49
2011-08-09 13:11:20 +00:00
28 changed files with 3136 additions and 224 deletions

1
.version Normal file
View File

@@ -0,0 +1 @@
2.6.0

1831
ChangeLog Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -176,6 +176,9 @@ $(LTZ_SO): $(LTZ_SO_OBJS)
dahdi_cfg: $(LTZ_A)
dahdi_cfg: LIBS+=-lm
dahdi_pcap:
$(CC) $(CFLAGS) dahdi_pcap.c -lpcap -o $@ $<
fxstest: $(LTZ_SO)
fxstest: LIBS+=-lm
@@ -345,6 +348,7 @@ clean:
rm -f core
rm -f dahdi_cfg-shared fxstest
rm -rf $(GENERATED_DOCS) *.asciidoc tonezones.txt
rm -f dahdi_pcap
distclean: dist-clean

View File

@@ -85,6 +85,13 @@ static struct dahdi_lineconfig lc[DAHDI_MAX_SPANS];
static struct dahdi_chanconfig cc[DAHDI_MAX_CHANNELS];
static int current_span = 0;
static int only_span = 0;
static int restrict_channels = 0;
static int selected_channels[DAHDI_MAX_CHANNELS];
static int chan2span[DAHDI_MAX_CHANNELS];
static int declared_spans[DAHDI_MAX_SPANS];
static struct dahdi_attach_echocan ae[DAHDI_MAX_CHANNELS];
static struct dahdi_dynamic_span zds[NUM_DYNAMIC];
@@ -228,6 +235,35 @@ static char *trim(char *buf)
return buf;
}
static int skip_channel(int x)
{
int spanno = chan2span[x];
if (restrict_channels) {
if (!selected_channels[x])
return 1;
/* sanity check */
if (only_span) {
if (spanno != 0 && only_span != spanno) {
fprintf(stderr,
"Only span %d. Skip selected channel %d from span %d\n",
only_span, x, spanno);
return 1;
}
}
} else {
if (only_span && !declared_spans[only_span]) {
fprintf(stderr,
"Error: analog span %d given to '-S', without '-C' restriction.\n",
only_span);
exit(1);
}
if (only_span && only_span != spanno)
return 1;
}
return 0;
}
static int parseargs(char *input, char *output[], int maxargs, char sep)
{
char *c;
@@ -258,11 +294,10 @@ static int parseargs(char *input, char *output[], int maxargs, char sep)
int dspanconfig(char *keyword, char *args)
{
static char *realargs[10];
int argc;
int res;
int chans;
int timing;
argc = res = parseargs(args, realargs, 4, ',');
res = parseargs(args, realargs, 4, ',');
if (res != 4) {
error("Incorrect number of arguments to 'dynamic' (should be <driver>,<address>,<num channels>, <timing>)\n");
return -1;
@@ -311,6 +346,8 @@ int spanconfig(char *keyword, char *args)
error("Span number should be a valid span number, not '%s'\n", realargs[0]);
return -1;
}
current_span = span;
declared_spans[span] = 1;
res = sscanf(realargs[1], "%d", &timing);
if ((res != 1) || (timing < 0) || (timing > MAX_TIMING)) {
error("Timing should be a number from 0 to %d, not '%s'\n",
@@ -482,6 +519,7 @@ static int chanconfig(char *keyword, char *args)
int master=0;
int dacschan = 0;
char *idle;
int is_digital;
bzero(chans, sizeof(chans));
strtok(args, ":");
idle = strtok(NULL, ":");
@@ -493,6 +531,7 @@ static int chanconfig(char *keyword, char *args)
if (res <= 0)
return -1;
for (x=1;x<DAHDI_MAX_CHANNELS;x++) {
is_digital = 0;
if (chans[x]) {
if (slineno[x]) {
error("Channel %d already configured as '%s' at line %d\n", x, sig[x], slineno[x]);
@@ -538,6 +577,7 @@ static int chanconfig(char *keyword, char *args)
return -1;
cc[x].sigtype = DAHDI_SIG_CAS;
sig[x] = sigtype_to_str(cc[x].sigtype);
is_digital = 1;
} else if (!strcasecmp(keyword, "dacs")) {
/* Setup channel for monitor */
cc[x].idlebits = dacschan;
@@ -548,6 +588,7 @@ static int chanconfig(char *keyword, char *args)
cc[dacschan].sigtype = DAHDI_SIG_DACS;
sig[x] = sigtype_to_str(cc[dacschan].sigtype);
dacschan++;
is_digital = 1;
} else if (!strcasecmp(keyword, "dacsrbs")) {
/* Setup channel for monitor */
cc[x].idlebits = dacschan;
@@ -557,6 +598,7 @@ static int chanconfig(char *keyword, char *args)
cc[dacschan].idlebits = x;
cc[dacschan].sigtype = DAHDI_SIG_DACS_RBS;
sig[x] = sigtype_to_str(cc[dacschan].sigtype);
is_digital = 1;
dacschan++;
} else if (!strcasecmp(keyword, "unused")) {
cc[x].sigtype = 0;
@@ -564,6 +606,7 @@ static int chanconfig(char *keyword, char *args)
} else if (!strcasecmp(keyword, "indclear") || !strcasecmp(keyword, "bchan")) {
cc[x].sigtype = DAHDI_SIG_CLEAR;
sig[x] = sigtype_to_str(cc[x].sigtype);
is_digital = 1;
} else if (!strcasecmp(keyword, "clear")) {
sig[x] = sigtype_to_str(DAHDI_SIG_CLEAR);
if (master) {
@@ -573,6 +616,7 @@ static int chanconfig(char *keyword, char *args)
cc[x].sigtype = DAHDI_SIG_CLEAR;
master = x;
}
is_digital = 1;
} else if (!strcasecmp(keyword, "rawhdlc")) {
sig[x] = sigtype_to_str(DAHDI_SIG_HDLCRAW);
if (master) {
@@ -582,6 +626,7 @@ static int chanconfig(char *keyword, char *args)
cc[x].sigtype = DAHDI_SIG_HDLCRAW;
master = x;
}
is_digital = 1;
} else if (!strcasecmp(keyword, "nethdlc")) {
sig[x] = sigtype_to_str(DAHDI_SIG_HDLCNET);
memset(cc[x].netdev_name, 0, sizeof(cc[x].netdev_name));
@@ -595,6 +640,7 @@ static int chanconfig(char *keyword, char *args)
}
master = x;
}
is_digital = 1;
} else if (!strcasecmp(keyword, "fcshdlc")) {
sig[x] = sigtype_to_str(DAHDI_SIG_HDLCFCS);
if (master) {
@@ -604,18 +650,26 @@ static int chanconfig(char *keyword, char *args)
cc[x].sigtype = DAHDI_SIG_HDLCFCS;
master = x;
}
is_digital = 1;
} else if (!strcasecmp(keyword, "dchan")) {
sig[x] = "D-channel";
cc[x].sigtype = DAHDI_SIG_HDLCFCS;
is_digital = 1;
} else if (!strcasecmp(keyword, "hardhdlc")) {
sig[x] = "Hardware assisted D-channel";
cc[x].sigtype = DAHDI_SIG_HARDHDLC;
is_digital = 1;
} else if (!strcasecmp(keyword, "mtp2")) {
sig[x] = "MTP2";
cc[x].sigtype = DAHDI_SIG_MTP2;
is_digital = 1;
} else {
fprintf(stderr, "Huh? (%s)\n", keyword);
}
if (is_digital)
chan2span[x] = current_span;
else
current_span = 0;
}
}
return 0;
@@ -667,6 +721,8 @@ static void apply_fiftysix(void)
int chanfd;
for (x = 1; x < DAHDI_MAX_CHANNELS; x++) {
if (skip_channel(x))
continue;
chanfd = open("/dev/dahdi/channel", O_RDWR);
if (chanfd == -1) {
fprintf(stderr,
@@ -755,13 +811,12 @@ static int unimplemented(char *keyword, char *args)
int ctcss(char *keyword, char *args)
{
static char *realargs[10];
int argc;
int res;
int rxtone;
int rxtag;
int txtone;
int isdcs = 0;
argc = res = parseargs(args, realargs, 3, ',');
res = parseargs(args, realargs, 3, ',');
if (res != 3) {
error("Incorrect number of arguments to 'ctcss' (should be <rxtone>,<rxtag>,<txtone>)\n");
return -1;
@@ -808,10 +863,9 @@ int ctcss(char *keyword, char *args)
int dcsrx(char *keyword, char *args)
{
static char *realargs[10];
int argc;
int res;
int rxtone;
argc = res = parseargs(args, realargs, 1, ',');
res = parseargs(args, realargs, 1, ',');
if (res != 1) {
error("Incorrect number of arguments to 'dcsrx' (should be <rxtone>)\n");
return -1;
@@ -831,11 +885,10 @@ int dcsrx(char *keyword, char *args)
int tx(char *keyword, char *args)
{
static char *realargs[10];
int argc;
int res;
int txtone;
int isdcs = 0;
argc = res = parseargs(args, realargs, 1, ',');
res = parseargs(args, realargs, 1, ',');
if (res != 1) {
error("Incorrect number of arguments to 'tx' (should be <txtone>)\n");
return -1;
@@ -860,10 +913,9 @@ int tx(char *keyword, char *args)
int debounce_time(char *keyword, char *args)
{
static char *realargs[10];
int argc;
int res;
int val;
argc = res = parseargs(args, realargs, 1, ',');
res = parseargs(args, realargs, 1, ',');
if (res != 1) {
error("Incorrect number of arguments to 'debouncetime' (should be <value>)\n");
return -1;
@@ -883,10 +935,9 @@ int debounce_time(char *keyword, char *args)
int burst_time(char *keyword, char *args)
{
static char *realargs[10];
int argc;
int res;
int val;
argc = res = parseargs(args, realargs, 1, ',');
res = parseargs(args, realargs, 1, ',');
if (res != 1) {
error("Incorrect number of arguments to 'bursttime' (should be <value>)\n");
return -1;
@@ -906,10 +957,9 @@ int burst_time(char *keyword, char *args)
int tx_gain(char *keyword, char *args)
{
static char *realargs[10];
int argc;
int res;
int val;
argc = res = parseargs(args, realargs, 1, ',');
res = parseargs(args, realargs, 1, ',');
if (res != 1) {
error("Incorrect number of arguments to 'txgain' (should be <value>)\n");
return -1;
@@ -927,10 +977,9 @@ int tx_gain(char *keyword, char *args)
int rx_gain(char *keyword, char *args)
{
static char *realargs[10];
int argc;
int res;
int val;
argc = res = parseargs(args, realargs, 1, ',');
res = parseargs(args, realargs, 1, ',');
if (res != 1) {
error("Incorrect number of arguments to 'rxgain' (should be <value>)\n");
return -1;
@@ -948,10 +997,9 @@ int rx_gain(char *keyword, char *args)
int de_emp(char *keyword, char *args)
{
static char *realargs[10];
int argc;
int res;
int val;
argc = res = parseargs(args, realargs, 1, ',');
res = parseargs(args, realargs, 1, ',');
if (res != 1) {
error("Incorrect number of arguments to 'de-emp' (should be <value>)\n");
return -1;
@@ -971,10 +1019,9 @@ int de_emp(char *keyword, char *args)
int pre_emp(char *keyword, char *args)
{
static char *realargs[10];
int argc;
int res;
int val;
argc = res = parseargs(args, realargs, 1, ',');
res = parseargs(args, realargs, 1, ',');
if (res != 1) {
error("Incorrect number of arguments to 'pre_emp' (should be <value>)\n");
return -1;
@@ -994,10 +1041,9 @@ int pre_emp(char *keyword, char *args)
int invert_cor(char *keyword, char *args)
{
static char *realargs[10];
int argc;
int res;
int val;
argc = res = parseargs(args, realargs, 1, ',');
res = parseargs(args, realargs, 1, ',');
if (res != 1) {
error("Incorrect number of arguments to 'invertcor' (should be <value>)\n");
return -1;
@@ -1021,10 +1067,9 @@ int invert_cor(char *keyword, char *args)
int ext_tone(char *keyword, char *args)
{
static char *realargs[10];
int argc;
int res;
int val;
argc = res = parseargs(args, realargs, 1, ',');
res = parseargs(args, realargs, 1, ',');
if (res != 1) {
error("Incorrect number of arguments to 'exttone' (should be <value>)\n");
return -1;
@@ -1050,11 +1095,10 @@ int ext_tone(char *keyword, char *args)
int cor_thresh(char *keyword, char *args)
{
static char *realargs[10];
int argc;
int res;
int val;
int x = 0;
argc = res = parseargs(args, realargs, 1, ',');
res = parseargs(args, realargs, 1, ',');
if (res != 1) {
error("Incorrect number of arguments to 'corthresh' (should be <value>)\n");
return -1;
@@ -1227,6 +1271,8 @@ static void printconfig(int fd)
"Configuration\n"
"======================\n\n", vi.version, vi.echo_canceller);
for (x = 0; x < spans; x++) {
if (only_span && only_span != x)
continue;
printf("SPAN %d: %3s/%4s Build-out: %s\n",
lc[x].span,
(lc[x].lineconfig & DAHDI_CONFIG_D4 ? "D4" :
@@ -1244,6 +1290,8 @@ static void printconfig(int fd)
if (verbose > 1) {
printf("\nChannel map:\n\n");
for (x=1;x<DAHDI_MAX_CHANNELS;x++) {
if (skip_channel(x))
continue;
if ((cc[x].sigtype != DAHDI_SIG_SLAVE) && (cc[x].sigtype)) {
configs++;
ps = 0;
@@ -1267,6 +1315,8 @@ static void printconfig(int fd)
}
} else {
for (x=1;x<DAHDI_MAX_CHANNELS;x++) {
if (skip_channel(x))
continue;
if (cc[x].sigtype)
configs++;
}
@@ -1361,11 +1411,39 @@ static void usage(char *argv0, int exitcode)
" -h -- Generate this help statement\n"
" -s -- Shutdown spans only\n"
" -t -- Test mode only, do not apply\n"
" -C <chan_list> -- Only configure specified channels\n"
" -S <spanno> -- Only configure specified span\n"
" -v -- Verbose (more -v's means more verbose)\n"
,c);
exit(exitcode);
}
static int chan_restrict(char *str)
{
if (apply_channels(selected_channels, str) < 0)
return 0;
restrict_channels = 1;
return 1;
}
static int span_restrict(char *str)
{
long spanno;
char *endptr;
spanno = strtol(str, &endptr, 10);
if (endptr == str) {
fprintf(stderr, "Missing valid span number after '-S'\n");
return 0;
}
if (*endptr != '\0') {
fprintf(stderr, "Extra garbage after span number in '-S'\n");
return 0;
}
only_span = spanno;
return 1;
}
int main(int argc, char *argv[])
{
int c;
@@ -1373,7 +1451,7 @@ int main(int argc, char *argv[])
char *key, *value;
int x,found;
while((c = getopt(argc, argv, "fthc:vsd::")) != -1) {
while((c = getopt(argc, argv, "fthc:vsd::C:S:")) != -1) {
switch(c) {
case 'c':
filename=optarg;
@@ -1396,6 +1474,14 @@ int main(int argc, char *argv[])
case 's':
stopmode = 1;
break;
case 'C':
if (!chan_restrict(optarg))
usage(argv[0], 1);
break;
case 'S':
if (!span_restrict(optarg))
usage(argv[0], 1);
break;
case 'd':
if (optarg)
debug = atoi(optarg);
@@ -1478,6 +1564,8 @@ finish:
}
if (stopmode) {
for (x=0;x<spans;x++) {
if (only_span && x != only_span)
continue;
if (ioctl(fd, DAHDI_SHUTDOWN, &lc[x].span)) {
fprintf(stderr, "DAHDI shutdown failed: %s\n", strerror(errno));
close(fd);
@@ -1487,6 +1575,8 @@ finish:
exit(1);
}
for (x=0;x<spans;x++) {
if (only_span && x != only_span)
continue;
if (ioctl(fd, DAHDI_SPANCONFIG, lc + x)) {
fprintf(stderr, "DAHDI_SPANCONFIG failed on span %d: %s (%d)\n", lc[x].span, strerror(errno), errno);
close(fd);
@@ -1504,7 +1594,14 @@ finish:
struct dahdi_params current_state;
int master;
int needupdate = force;
if (skip_channel(x)) {
if (debug & DEBUG_APPLY) {
printf("Skip device %d\n", x);
fflush(stdout);
}
continue;
}
if (debug & DEBUG_APPLY) {
printf("Configuring device %d\n", x);
fflush(stdout);
@@ -1657,6 +1754,8 @@ finish:
}
}
for (x=0;x<spans;x++) {
if (only_span && x != only_span)
continue;
if (ioctl(fd, DAHDI_STARTUP, &lc[x].span)) {
fprintf(stderr, "DAHDI startup failed: %s\n", strerror(errno));
close(fd);

View File

@@ -53,12 +53,14 @@ void display_help(char *argv0, int exitcode)
fprintf(stderr, " -h, --help display help\n");
fprintf(stderr, " -s, --span <span num> specify the span\n");
fprintf(stderr, " -l, --loopback <localhost|networkline|"\
"networkpayload|off>\n"\
"networkpayload|loopup|"\
"loopdown|off>\n"\
"\t\tlocalhost - loop back towards host\n"\
"\t\tnetworkline - network line loopback\n"\
"\t\tnetworkpayload - network payload loopback\n"\
"\t\tloopup - transmit loopup signal\n"\
"\t\tloopdown - transmit loopdown signal\n");
"\t\tloopdown - transmit loopdown signal\n"\
"\t\toff - end loopback mode\n");
fprintf(stderr, " -i, --insert <fas|multi|crc|cas|prbs|bipolar>"\
"\n\t\tinsert an error of a specific type\n");
fprintf(stderr, " -r, --reset "\
@@ -79,7 +81,6 @@ int main(int argc, char *argv[])
int doloopback = 0;
char *larg = NULL;
int sflag = 0;
int span = 1;
int iflag = 0;
char *iarg = NULL;
@@ -107,16 +108,15 @@ int main(int argc, char *argv[])
while ((c = getopt_long(argc, argv, "hj:l:p:s:i:g:r",
long_options, &option_index)) != -1) {
switch (c) {
case 'h': /* local host loopback */
case 'h':
display_help(argv[0], 0);
break;
case 'l': /* network line loopback */
case 'l': /* loopback */
larg = optarg;
doloopback = 1;
break;
case 's': /* specify a span */
span = atoi(optarg);
sflag = 1;
break;
case 'i': /* insert an error */
iarg = optarg;
@@ -140,7 +140,7 @@ int main(int argc, char *argv[])
if (!(doloopback || iflag || gflag || rflag)) {
s.spanno = span;
res = ioctl(ctl, DAHDI_SPANSTAT, &s);
if (res)
if (res || ((__u32)-1 == s.fecount))
printf("Error counters not supported by the driver"\
" for this span\n");
printf("Span %d:\n", span);

332
dahdi_pcap.c Normal file
View File

@@ -0,0 +1,332 @@
/*
* Capturing a pcap from the DAHDI interface
*
* Copyright (C) 2011 Torrey Searle
*
* ISDN support added by Horacio Peña
* Command line cleanups by Sverker Abrahamsson
*
* Requirements:
* - pcap development library
* - DAHDI_MIRROR ioctl which isn't enabled by default in dahdi-linux
* To enable this unsupported feature, #define CONFIG_DAHDI_MIRROR
* in dahdi-linux
* - To build this program call the 'make dahdi_pcap' target
*/
/*
* See http://www.asterisk.org for more information about
* the Asterisk project. Please do not directly contact
* any of the maintainers of this project for assistance;
* the project provides a web site, mailing lists and IRC
* channels for your use.
*
* This program is free software, distributed under the terms of
* the GNU General Public License Version 2 as published by the
* Free Software Foundation. See the LICENSE file included with
* this program for more details.
*/
#include <stdio.h>
#include <fcntl.h>
#include <dahdi/user.h>
#include <sys/time.h>
#include <time.h>
#include <sys/types.h>
#include <unistd.h>
#include <string.h>
#include <pcap.h>
#include <sys/types.h>
#include <arpa/inet.h>
#include <sys/ioctl.h>
#include <stdlib.h>
#include <getopt.h>
#define BLOCK_SIZE 512
#define MAX_CHAN 16
//char ETH_P_LAPD[2] = {0x00, 0x30};
struct mtp2_phdr {
u_int8_t sent;
u_int8_t annex_a_used;
u_int16_t link_number;
};
struct lapd_sll_hdr {
u_int16_t sll_pkttype; /* packet type */
u_int16_t sll_hatype;
u_int16_t sll_halen;
u_int8_t sll_addr[8];
u_int8_t sll_protocol[2]; /* protocol, should be ETH_P_LAPD */
};
struct chan_fds {
int rfd;
int tfd;
int chan_id;
int proto;
char tx_buf[BLOCK_SIZE * 4];
int tx_len;
char rx_buf[BLOCK_SIZE * 4];
int rx_len;
};
int make_mirror(long type, int chan)
{
int res = 0;
int fd = 0;
struct dahdi_bufferinfo bi;
fd = open("/dev/dahdi/pseudo", O_RDONLY);
memset(&bi, 0, sizeof(bi));
bi.txbufpolicy = DAHDI_POLICY_IMMEDIATE;
bi.rxbufpolicy = DAHDI_POLICY_IMMEDIATE;
bi.numbufs = 32;
bi.bufsize = BLOCK_SIZE;
ioctl(fd, DAHDI_SET_BUFINFO, &bi);
res = ioctl(fd, type, &chan);
if(res)
{
printf("error setting channel err=%d!\n", res);
return -1;
}
return fd;
}
int log_packet(struct chan_fds * fd, char is_read, pcap_dumper_t * dump)
{
unsigned char buf[BLOCK_SIZE * 4];
int res = 0;
struct pcap_pkthdr hdr;
struct mtp2_phdr * mtp2 = (struct mtp2_phdr *)buf;
struct lapd_sll_hdr * lapd = (struct lapd_sll_hdr *)buf;
unsigned char *dataptr = buf;
int datasize = sizeof(buf);
if(fd->proto == DLT_LINUX_LAPD)
{
dataptr += sizeof(struct lapd_sll_hdr);
datasize -= sizeof(struct lapd_sll_hdr);
}
else
{
dataptr += sizeof(struct mtp2_phdr);
datasize -= sizeof(struct mtp2_phdr);
}
memset(buf, 0, sizeof(buf));
if(is_read)
{
res = read(fd->rfd, dataptr, datasize);
if(fd->rx_len > 0 && res == fd->rx_len && !memcmp(fd->rx_buf, dataptr, res) )
{
//skipping dup
return 0;
}
memcpy(fd->rx_buf, dataptr, res);
fd->rx_len = res;
}
else
{
res = read(fd->tfd, dataptr, datasize);
if(fd->tx_len > 0 && res == fd->tx_len && !memcmp(fd->tx_buf, dataptr, res) )
{
//skipping dup
return 0;
}
memcpy(fd->tx_buf, dataptr, res);
fd->tx_len = res;
}
gettimeofday(&hdr.ts, NULL);
if(res > 0)
{
if(fd->proto == DLT_LINUX_LAPD)
{
hdr.caplen = res+sizeof(struct lapd_sll_hdr)-2;
hdr.len = res+sizeof(struct lapd_sll_hdr)-2;
lapd->sll_pkttype = 3;
lapd->sll_hatype = 0;
lapd->sll_halen = res;
// lapd->sll_addr = ???
lapd->sll_protocol[0] = 0x00;
lapd->sll_protocol[1] = 0x30;
}
else
{
hdr.caplen = res+sizeof(struct mtp2_phdr);
hdr.len = res+sizeof(struct mtp2_phdr);
if(is_read)
{
mtp2->sent = 0;
mtp2->annex_a_used = 0;
}
else
{
mtp2->sent = 1;
mtp2->annex_a_used = 0;
}
mtp2->link_number = htons(fd->chan_id);
}
pcap_dump((u_char*)dump, &hdr, buf);
pcap_dump_flush(dump);
}
return 1;
}
void usage()
{
printf("Usage: dahdi_pcap [OPTIONS]\n");
printf("Capture packets from DAHDI channels to pcap file\n\n");
printf("Options:\n");
printf(" -p, --proto=[mtp2|lapd] The protocol to capture, default mtp2\n");
printf(" -c, --chan=<channels> Comma separated list of channels to capture from, max %d. Mandatory\n", MAX_CHAN);
printf(" -f, --file=<filename> The pcap file to capture to. Mandatory\n");
printf(" -h, --help Display this text\n");
}
int main(int argc, char **argv)
{
struct chan_fds chans[MAX_CHAN];
char *filename = NULL;
int num_chans = 0;
int max_fd = 0;
int proto = DLT_MTP2_WITH_PHDR;
int i;
int packetcount;
int c;
while (1) {
int option_index = 0;
static struct option long_options[] = {
{"proto", required_argument, 0, 'p'},
{"chan", required_argument, 0, 'c'},
{"file", required_argument, 0, 'f'},
{"help", 0, 0, 'h'},
{0, 0, 0, 0}
};
c = getopt_long(argc, argv, "p:c:f:?",
long_options, &option_index);
if (c == -1)
break;
switch (c) {
case 'p':
// Protocol
if(strcasecmp("LAPD", optarg)==0)
{
proto = DLT_LINUX_LAPD;
}
else if(argc > 0 && strcasecmp("MTP2", argv[1])==0)
{
proto = DLT_MTP2_WITH_PHDR;
}
break;
case 'c':
// TODO Should it be possible to override protocol per channel?
// Channels, comma separated list
while(optarg != NULL && num_chans < MAX_CHAN)
{
int chan = atoi(strsep(&optarg, ","));
chans[num_chans].tfd = make_mirror(DAHDI_TXMIRROR, chan);
chans[num_chans].rfd = make_mirror(DAHDI_RXMIRROR, chan);
chans[num_chans].chan_id = chan;
chans[num_chans].proto = proto;
if(chans[num_chans].tfd > max_fd)
{
max_fd = chans[num_chans].tfd;
}
if(chans[num_chans].rfd > max_fd)
{
max_fd = chans[num_chans].rfd;
}
num_chans++;
}
max_fd++;
break;
case 'f':
// File to capture to
filename=optarg;
break;
case 'h':
default:
// Usage
usage();
exit(0);
}
}
if((num_chans == 0) || (filename == NULL)) {
usage();
exit(0);
}
else
{
printf("Capturing protocol %s on channels ", (proto == DLT_MTP2_WITH_PHDR ? "mtp2":"lapd"));
for(i = 0; i < num_chans; i++)
{
printf("%d", chans[i].chan_id);
if(i<num_chans-1)
{
printf(", ");
}
}
printf(" to file %s\n", filename);
}
pcap_t * pcap = pcap_open_dead(chans[0].proto, BLOCK_SIZE*4);
pcap_dumper_t * dump = pcap_dump_open(pcap, filename);
packetcount=0;
while(1)
{
fd_set rd_set;
FD_ZERO(&rd_set);
for(i = 0; i < num_chans; i++)
{
FD_SET(chans[i].tfd, &rd_set);
FD_SET(chans[i].rfd, &rd_set);
}
select(max_fd, &rd_set, NULL, NULL, NULL);
for(i = 0; i < num_chans; i++)
{
if(FD_ISSET(chans[i].rfd, &rd_set))
{
packetcount += log_packet(&chans[i], 1, dump);
}
if(FD_ISSET(chans[i].tfd, &rd_set))
{
packetcount += log_packet(&chans[i], 0, dump);
}
}
printf("Packets captured: %d\r", packetcount);
fflush(stdout);
}
return 0;
}

View File

@@ -40,17 +40,32 @@
#define SIZE 8000
static int verbose;
static int pass = 0;
static float best = 0.0;
static float worst = 100.0;
static double total = 0.0;
static double delay_total = 0.0;
static double total_time = 0.0;
static double total_count = 0.0;
static inline float _fmin(float a, float b)
{
return (a < b) ? a : b;
}
static double calculate_accuracy(double count, double ms)
{
return ((count - _fmin(count, fabs(count - ms))) / count) * 100.0;
}
void hup_handler(int sig)
{
double accuracy = calculate_accuracy(total_count, total_time);
printf("\n--- Results after %d passes ---\n", pass);
printf("Best: %.3f -- Worst: %.3f -- Average: %f, Difference: %f\n",
best, worst, pass ? total/pass : 100.00, pass ? delay_total/pass : 100);
printf("Best: %.3f%% -- Worst: %.3f%% -- Average: %f%%\n",
best, worst, pass ? total/pass : 100.00);
printf("Cummulative Accuracy (not per pass): %0.3f\n",
pass ? accuracy : 0.0);
exit(0);
}
@@ -79,9 +94,7 @@ int main(int argc, char *argv[])
int count = 0;
int seconds = 0;
int curarg = 1;
int verbose = 0;
char buf[8192];
float score;
float ms;
struct timeval start, now;
fd = open("/dev/dahdi/pseudo", O_RDWR);
@@ -140,23 +153,23 @@ int main(int argc, char *argv[])
ms += (now.tv_sec - start.tv_sec) * 8000;
ms += (now.tv_usec - start.tv_usec) / 125.0;
if (count >= SIZE) {
double percent = 100.0 * (count - ms) / count;
const double percent = calculate_accuracy(count, ms);
if (verbose) {
printf("\n%d samples in %0.3f system clock sample intervals (%.3f%%)",
count, ms, 100 - percent);
count, ms, percent);
} else if (pass > 0 && (pass % 8) == 0) {
printf("\n");
}
score = 100.0 - fabs(percent);
if (score > best)
best = score;
if (score < worst)
worst = score;
if (percent > best)
best = percent;
if (percent < worst)
worst = percent;
if (!verbose)
printf("%.3f%% ", score);
total += score;
delay_total += 100 - percent;
printf("%.3f%% ", percent);
total += percent;
fflush(stdout);
total_count += count;
total_time += ms;
count = 0;
pass++;
}

View File

@@ -4,7 +4,7 @@
dahdi_cfg \- configures DAHDI kernel modules from /etc/dahdi/system.conf
.SH SYNOPSIS
.B dahdi_cfg [\-c \fICFG_FILE\fB] [\-s] [\-f] [\-t] [\-v [\-v ... ] ]
.B dahdi_cfg [\-c \fICFG_FILE\fB] [\-S\fINUM\fB [-S\fICHANS\fB]] [\-s] [\-f] [\-t] [\-v [\-v ... ] ]
.B dahdi_cfg \-h
@@ -26,11 +26,25 @@ Use an alternative configuration file instead of
.I /etc/dahdi/system.conf
.RE
.B \-C \fICHANNELS
.RS
Only apply changes to channels in the specified range. Only
applicable when \-S is in use.
.RE
.B \-s
.RS
Only shutdown spans.
.RE
.B \-S \fISPAN
.RS
Only apply changes to span no. \fISPAN\fR. For a digital span (with
a 'span=' line in the configuration file) this will do. For an analog
span you'll have to explicitly tell dahdi_cfg the range of channels,
using \-C .
.RE
.B \-f
.RS
Always configure every channel, even if it appears not to have changed.

62
doc/dahdi_maint.8 Normal file
View File

@@ -0,0 +1,62 @@
.TH "DAHDI_MAINT" "8" "9 Sep 2011" "" ""
.SH NAME
dahdi_maint \- Sets Dahdi spans into maintenance mode, e.g.: loopback
.SH SYNOPSIS
.B dahdi_maint \-s \fInum\fB [options]
.B dahdi_maint <\-h|\-\-help>
.SH DESCRIPTION
dahdi_maint uses the DAHDI_MAINT interface to set a Dahdi span (port
of a Dahdi adapter card) into loopback mode or similar maintenance mode.
.SH OPTIONS
.B \-s \-\-span \fInum\fR
.RS
The span number. Required.
.RE
.B \-l \-\-loopback <localhost|networkline|networkpayload|loopup|loopdown|off>
.RS
Loopback type. One of:
.IP localhost 4
loop back towards host
.IP networkline 4
network line loopback
.IP networkpayload 4
network payload loopback
.IP loopup 4
transmit loopup signal
.IP loopdown 4
transmit loopdown signal
.IP off 4
end loopback mode
.RE
.B \-i \-\-insert <fas|multi|crc|cas|prbs|bipolar>
.RS
Insert an error of a specific type
.RE
.SH EXAMPLES
Enable network line loopback on span 1:
dahdi_maint -s 1 --loopback networkline
Disable network line loopback on span 1:
dahdi_maint -s 1 --loopback off
.SH SEE ALSO
.PP
dahdi_tool(8), dahdi_cfg(8), asterisk(8).
.SH AUTHOR
.PP
This manual page was written by Tzafrir Cohen <tzafrir.cohen@xorcom.com>.
Permission is granted to copy, distribute and/or modify this document
under the terms of the GNU General Public License, Version 2 any later
version published by the Free Software Foundation.

View File

@@ -1,37 +1,139 @@
.TH "DAHDI_MONITOR" "8" "16 June 2008" "" ""
.TH "DAHDI_MONITOR" "8" "9 Sep 2011" "" ""
.SH NAME
dahdi_monitor \- checks the rx/tx levels of DAHDI channels
dahdi_monitor \- checks the Rx/Tx levels of a DAHDI channels
.SH SYNOPSIS
.B dahdi_monitor \fIchannel number\fB [\-v] [\-f \fIFILE\fB]
.B dahdi_monitor \fInum\fB [\-v[v]]
.B dahdi_monitor \fInum\fB [\-o] [<\-f|\-F> \fIFILE\fB]
.B dahdi_monitor \fInum\fB [[<\-r|\-R> \fIFILE\fB]] [[<\-t|\-T> \fIFILE\fB]]
.SH DESCRIPTION
dahdi_monitor monitors a DAHDI channel. It gives you a visual
representation of the sound strengths and makes it easy to see if
the received or transmitted signals are too high or out of
balance
dahdi_monitor monitors a Dahdi channel. It can record the output to a
file, play it to the speaker, or visualize the audio levels on the
terminal.
Recorded audio files are by default raw signed linear PCM. If the file
name ends with ".wav", the recorded file will be a WAV file.
The visual display shows the current audio level at both the Rx
(audio Received by Asterisk) and
Tx (audio Transmitted by Asterisk)
To exit the program, press Ctrl-C.
.SH OPTIONS
The first (mandatory) parameter is the number of the channel
to monitor.
.B \-m
.RS
Multiple channels. Don't multiplex both Rx and Tx in a single channel.
Normally there's a different option that you need that implies it.
.RE
.B \-o
.RS
Plays the output to OSS (/dev/dsp). Requires -m not to be used.
.RE
.B \-v
.RS
Display visual audio levels.
Display Visual audio levels. With two v-s, Verbose mode is enabled, that
shows the actual levels as numbers. Note that this requires a terminal
wider than 80 columns to be properly displayed.
Implies -m.
.RE
.B \-f \fIFILE
.RS
Write output to FILE
Record the content of the channel (Tx + Rx) to a file.
.RE
Some extra, yet undocumented, options.
.B \-F \fIFILE
.RS
Record the content of the channel (Tx + Rx) before the echo canceler
to a file.
.RE
.B \-r \fIFILE
.RS
Record the content of the Rx channel to a file.
Implies -m.
.RE
.B \-R \fIFILE
.RS
Record the content of the R channel before the echo canceler to a file.
Implies -m.
.RE
.B \-s \fIFILE
.RS
Record the content of the Tx and Rx of the channel to a file.
.RE
.B \-S \fIFILE
.RS
Records a stereo of both Tx and Rx of the channel before the echo
canceler to a file.
.RE
.B \-t \fIFILE
.RS
Record the content of the Tx channel to a file.
Implies -m.
.RE
.B \-T \fIFILE
.RS
Record the content of the Tx channel before the echo canceler to a file.
Implies -m.
.RE
.SH EXAMPLES
Visualize audio levels on DAHDI channel 2:
dahdi_monitor 2 -v
Record channel 3 to a file:
dahdi_monitor 3 -f output.raw
This will create a raw PCM file (signed-linear, 8kHz, mono, 16 bits per
sample). Both the Tx and Rx will be multiplexed in a single channel.
It can be converted to a WAV file using e.g.:
sox -s -c1 -2 -r8000 output.raw output.wav
Record Tx and Rx of channel 5 to separate files. This time directly to
WAV files:
dahdi_monitor 5 -r output_rx.wav -t output_tx.wav
Record channel 8 to a stereo file (Tx and Rx on its two channels):
dahdi_monitor 8 -s output.raw
Converting it to a WAV file:
sox -s -c2 -2 -r8000 output.raw output.wav
.SH SEE ALSO
.PP
dahdi_tool(8), dahdi_cfg(8), asterisk(8).
dahdi_tool(8), dahdi_cfg(8).
.SH AUTHOR
.PP

View File

@@ -43,27 +43,42 @@ an FXO module of two ports.
Building and Installation
-------------------------
Apart from the standard DAHDI build requirements, you also need libusb
development headers to build the fpga_load firmware loader. This is
typically the package libusb-dev on Debian (and derivatives like Ubuntu)
or libusb-devel on RedHat (and derivatives like CentOS/Trixbox).
Apart from the standard DAHDI build requirements, you also need:
Patch for BRI
~~~~~~~~~~~~~
(As of DAHDI 2.2 this patch is no longer needed. Furthermore, it does
not apply. The same directory has a newer patch that applies. This
section is kept in the document for the time being for the benefit of
those with older versions)
* *libusb development headers* to build the fpga_load firmware loader.
This is typically the package libusb-dev on Debian (and derivatives
like Ubuntu) or libusb-devel on RedHat (and derivatives like
CentOS/Trixbox).
* *Echo Canceller Module firmware*: If you have an Astribank with an
echo canceller module, see the following section.
In order for the BRI module (xpd_bri.ko) to build, you still need an
external patch:
Follow the build instructions of DAHDI-linux and DAHDI-tools. But
Basically, in dahdi-linux run:
http://updates.xorcom.com/astribank/bristuff/dahdi_bri_dchan.diff[]
make
make install # as root
You need to apply it to the dahdi-linux tarball before building:
And later in dahdi-tools:
wget http://updates.xorcom.com/astribank/bristuff/dahdi_bri_dchan.diff
patch -p1 <dahdi_bri_dchan.diff
./configure
make
make install # as root
Echo Canceller Firmware
~~~~~~~~~~~~~~~~~~~~~~~
If you install from source, you should copy OCT6104E-256D.ima to the
source tree (before running make install:
wget http://updates.xorcom.com/astribank/hwec/OCT6104E-256D.ima
mv OCT6104E-256D.ima drivers/dahdi/xpp/firmwares/
Alternatively, if you have already installed DAHDI-linux (e.g. from a
binary package that does not include the firmware) you can just copy
it directly to the target directory, /usr/share/dahdi using:
cd /usr/share/dahdi
wget http://updates.xorcom.com/astribank/hwec/OCT6104E-256D.ima
Installation Scenarios

View File

@@ -33,7 +33,7 @@ information used by Xorcom to generate/modify licensed capabilities.
Required. The device to read from/write to. This is
\fIbus_num\fR/\fIdevice_num\fR, where \fIbus_num\fR and \fIdevice_num\fR
are the first two numbers in the output of lsusb(8) or dahdi_hardware(8).
On older versions of this toolyou needed a complete path to the device,
On older versions of this tool you needed a complete path to the device,
which would be /dev/bus/usb/\fIbus_num\fR/\fIdevice_num\fR, or
/proc/bus/usb/\fIbus_num\fR/\fIdevice_num\fR.
.RE

View File

@@ -31,7 +31,7 @@ firmware. It is normally run by the script xpp_fxloader.
Required. The device to read from/write to. This is
\fIbus_num\fR/\fIdevice_num\fR, where \fIbus_num\fR and \fIdevice_num\fR
are the first two numbers in the output of lsusb(8) or dahdi_hardware(8).
On older versions of this toolyou needed a complete path to the device,
On older versions of this tool you needed a complete path to the device,
which would be /dev/bus/usb/\fIbus_num\fR/\fIdevice_num\fR, or
/proc/bus/usb/\fIbus_num\fR/\fIdevice_num\fR.
.RE

View File

@@ -24,6 +24,7 @@
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stdarg.h>
#include <errno.h>
#include <assert.h>
#include <arpa/inet.h>
@@ -36,7 +37,7 @@
#include "../autoconfig.h"
#define DBG_MASK 0x80
#define MAX_HEX_LINES 10000
#define MAX_HEX_LINES 64000
#define HAVE_OCTASIC 1
static char *progname;
@@ -81,15 +82,27 @@ int handle_hexline(struct astribank_device *astribank, struct hexline *hexline)
return 0;
}
void print_parse_errors(int level, const char *msg, ...)
{
va_list ap;
if (verbose > level) {
va_start (ap, msg);
vfprintf (stderr, msg, ap);
va_end (ap);
}
}
static int load_hexfile(struct astribank_device *astribank, const char *hexfile, enum dev_dest dest)
{
struct hexdata *hexdata = NULL;
int finished = 0;
int ret;
int i;
unsigned i;
char star[] = "+\\+|+/+-";
const char *devstr;
parse_hexfile_set_reporting(print_parse_errors);
if((hexdata = parse_hexfile(hexfile, MAX_HEX_LINES)) == NULL) {
perror(hexfile);
return -errno;
@@ -100,13 +113,6 @@ static int load_hexfile(struct astribank_device *astribank, const char *hexfile,
xusb_serial(astribank->xusb),
dev_dest2str(dest),
hexdata->fname, hexdata->version_info);
#if 0
FILE *fp;
if((fp = fopen("fpga_dump_new.txt", "w")) == NULL) {
perror("dump");
exit(1);
}
#endif
if((ret = mpp_send_start(astribank, dest, hexdata->version_info)) < 0) {
ERR("%s: Failed hexfile send start: %d\n", devstr, ret);
return ret;

View File

@@ -20,7 +20,7 @@ to the \-D command line option).
Required. The device to read from/write to. This is
\fIbus_num\fR/\fIdevice_num\fR, where \fIbus_num\fR and \fIdevice_num\fR
are the first two numbers in the output of lsusb(8) or dahdi_hardware(8).
On older versions of this toolyou needed a complete path to the device,
On older versions of this tool you needed a complete path to the device,
which would be /dev/bus/usb/\fIbus_num\fR/\fIdevice_num\fR, or
/proc/bus/usb/\fIbus_num\fR/\fIdevice_num\fR.
.RE

View File

@@ -64,6 +64,8 @@ static const struct xusb_spec astribank_specs[] = {
TYPE_ENTRY("USB-MULTI", 0x1161, 2, 1, 2, MP_EP_OUT, MP_EP_IN),
TYPE_ENTRY("FPGA-MULTI", 0x1162, 2, 1, 2, MP_EP_OUT, MP_EP_IN),
TYPE_ENTRY("BURNED-MULTI", 0x1164, 2, 1, 2, MP_EP_OUT, MP_EP_IN),
TYPE_ENTRY("USB-BURN", 0x1112, 2, 1, 2, MP_EP_OUT, MP_EP_IN),
};
static const struct xusb_spec astribank_pic_specs[] = {

View File

@@ -111,7 +111,7 @@ __END__
=head1 NAME
dahdi_genconf - Generate configuration for dahdi channels.
dahdi_genconf - Generate configuration for Dahdi channels.
=head1 SYNOPSIS
@@ -126,7 +126,7 @@ It uses two information sources:
=item Hardware
The actual dahdi hardware is automatically detected on the host.
The actual Dahdi hardware is automatically detected on the host.
=item /etc/dahdi/genconf_parameters
@@ -137,7 +137,7 @@ variable.
=back
The dahdi_genconf script can generate various kinds of configuration files
as specificed by the generator arguments. Each generator is a perl classes
as specified by the generator arguments. Each generator is a perl class
in Dahdi::Config::Gen namespace. The generator names on the command line
are the class names in lowercase.
@@ -177,14 +177,14 @@ Currently, chandahdi is affected.
=item *
F<genconf_parameters> parsing is done via C<Dahdi::Config::Params>.
An object representing the parsed data is instanciated by:
An object representing the parsed data is instantiated by:
C<Dahdi::Config::Params-E<gt>new()>.
The C<item()> method of this object contains all the hard coded
defaults of the configuration directives.
=item *
A configuration object is instanciated by C<Dahdi::Config::Gen-E<gt>new($params)>.
A configuration object is instantiated by C<Dahdi::Config::Gen-E<gt>new($params)>.
The mapping of configuration directives into semantic configuration is
done in the constructor.

View File

@@ -72,7 +72,7 @@ sub show_disconnected(%) {
# FIXME: For verbose display we also need to see the XPP devices.
# If no spans are registered, this won't happen. A brute-force
# methood for making it happe:
# method for making it happen:
Dahdi::Xpp::xbuses if ($opts{'v'});
my @devices = Dahdi::Hardware->device_list;
@@ -139,7 +139,7 @@ dahdi_hardware [-v][-x]
=item -v
Verbose ouput - show spans used by each device etc. Currently only
Verbose output - show spans used by each device etc. Currently only
implemented for the Xorcom Astribank.
=item -x
@@ -150,7 +150,7 @@ Show disconnected Astribank unit, if any.
=head1 DESCRIPTION
Show all dahdi hardware devices. Devices are recognized according to
Show all Dahdi hardware devices. Devices are recognized according to
lists of PCI and USB IDs in Dahdi::Hardware::PCI.pm and
Dahdi::Hardware::USB.pm . For PCI it is possible to detect by
sub-vendor and sub-product ID as well.

View File

@@ -48,7 +48,7 @@ __END__
=head1 NAME
lsdahdi - List all dahdi channels with their types and spans.
lsdahdi - List all Dahdi channels with their types and spans.
=head1 SYNOPSIS

View File

@@ -168,7 +168,7 @@ sub gen_channel($$) {
die "missing context for chan #$num type $type" unless $context;
$callerid = ($type eq 'FXO')
? 'asreceived'
: sprintf "\"Channel %d\" <%04d>", $num, $exten;
: sprintf "\"Channel %d\" <%d>", $num, $exten;
if($type eq 'IN') {
$immediate = 'yes';
}
@@ -182,7 +182,7 @@ sub gen_channel($$) {
printf ";;; line=\"%d %s%s%s\"\n", $num, $chan->fqn, $signalling, $info;
printf "signalling=$sig\n";
printf "callerid=$callerid\n";
printf "mailbox=%04d\n", $exten unless $type eq 'FXO';
printf "mailbox=%d\n", $exten unless $type eq 'FXO';
if(defined $group) {
printf "group=$group\n";
}

View File

@@ -0,0 +1,116 @@
package Dahdi::Config::Gen::Freepbxdb;
# Written by Tzafrir Cohen <tzafrir.cohen@xorcom.com>
# Copyright (C) 2011, Xorcom
# This program is free software; you can redistribute and/or
# modify it under the same terms as Perl itself.
use strict;
use Socket;
use Dahdi::Config::Gen qw(is_true);
sub new($$$) {
my $pack = shift || die;
my $gconfig = shift || die;
my $genopts = shift || die;
my $self = {
GCONFIG => $gconfig,
GENOPTS => $genopts,
};
bless $self, $pack;
return $self;
}
sub gen_channel($$) {
my $self = shift || die;
my $chan = shift || die;
my $gconfig = $self->{GCONFIG};
my $type = $chan->type;
my $num = $chan->num;
die "channel $num type $type is not an analog channel\n" if $chan->span->is_digital();
my $exten = $gconfig->{'base_exten'} + $num;
my $callerid = sprintf "\"Channel %d\" <%04d>", $num, $exten;
my @cmds = ();
#push @cmds, "database put DEVICE/$exten default_user $exten";
#push @cmds, "database put DEVICE/$exten dial ZAP/$num";
push @cmds, "database put DEVICE/$exten dial DAHDI/$num";
#push @cmds, "database put DEVICE/$exten type fixed";
push @cmds, "database put DEVICE/$exten user $exten";
push @cmds, "database put AMPUSER/$exten device $exten";
push @cmds, "database put AMPUSER/$exten cidname $callerid";
return @cmds;
}
sub generate($) {
my $self = shift || die;
my $gconfig = $self->{GCONFIG};
my $genopts = $self->{GENOPTS};
#$gconfig->dump;
my $ast_sock = '/var/run/asterisk/asterisk.ctl';
my @spans = @_;
my @cmds = ();
warn "Empty configuration -- no spans\n" unless @spans;
print "Configuring FXSs for FreePBX\n" if $genopts->{verbose};
foreach my $span (@spans) {
next if $span->is_digital;
foreach my $chan ($span->chans()) {
next unless ($chan->type eq 'FXS');
push @cmds, $self->gen_channel($chan);
}
}
#open(CMDS,"|$command >/dev/null") or
socket(SOCK, PF_UNIX, SOCK_STREAM, 0) || die "socket: $!";
connect(SOCK, sockaddr_un($ast_sock)) ||
die "$0: Freepbxdb: Failed connecting to $ast_sock\n: $!";
foreach (@cmds) {
# Note: commands are NULL-terminated:
print SOCK "$_\0";
sleep 0.001;
}
close(SOCK) or
die "$0: Freepbxdb: Failed sending commands ($ast_sock): $!\n";
}
1;
__END__
=head1 NAME
freepbxdb - Generate astdb configuration required by FreePBX
=head1 SYNOPSIS
use Dahdi::Config::Gen::Freepbxdb;
my $cfg = new Dahdi::Config::Gen::Freepbxdb(\%global_config, \%genopts);
$cfg->generate(@span_list);
=head1 DESCRIPTION
Updates the Asterisk DB entries for FXS channels detected. Requires
Asterisk running.
The configuration generated here bypasses FreePBX's standard configuration
and allows using a simple dialplan snippet such as:
[from-internal-custom](+)
exten => _4XXX,1,Dial(DAHDI/${EXTEN:1})
This may come in handy in testing. At least until FreePBX will provide a
simple automated interface to do the same.
=head1 OPTIONS
None, so far.
=head1 FILES
=over
=item C</var/run/asterisk/asterisk.sock>
The socket to which commands are sent. FIXME: make this a parameter.
=back

View File

@@ -30,7 +30,7 @@ sub get_sorted_xbuses(@) {
my @sorted_xbuses;
foreach my $xbus (@xbuses) {
my $last_spanno;
foreach my $xpd ($xbus->xpds) {
foreach my $xpd (Dahdi::Xpp::Xpd::telephony_devs($xbus->xpds())) {
my $spanno = $xpd->spanno;
if(!$spanno) {
printf STDERR "%s: Is not registered. Skipping.\n", $xpd->fqn;

View File

@@ -133,7 +133,7 @@ my %pci_ids = (
'0b0b:0105' => { DRIVER => 'r1t1', DESCRIPTION => 'Rhino R1T1' },
'0b0b:0205' => { DRIVER => 'r4fxo', DESCRIPTION => 'Rhino R14FXO' },
'0b0b:0206' => { DRIVER => 'rcbfx', DESCRIPTION => 'Rhino RCB4FXO 4-channel FXO analog telphony card' },
'0b0b:0305' => { DRIVER => 'r1t1', DESCRIPTION => 'Rhino R1T1' },
'0b0b:0305' => { DRIVER => 'rxt1', DESCRIPTION => 'Rhino R4T1' },
'0b0b:0405' => { DRIVER => 'rcbfx', DESCRIPTION => 'Rhino R8FXX' },
'0b0b:0406' => { DRIVER => 'rcbfx', DESCRIPTION => 'Rhino RCB8FXX 8-channel modular analog telphony card' },
'0b0b:0505' => { DRIVER => 'rcbfx', DESCRIPTION => 'Rhino R24FXX' },
@@ -203,7 +203,7 @@ sub scan_devices($) {
$pci_devs{$name}{DRIVER} = '';
}
while(</sys/bus/pci/drivers/*/[0-9]*>) {
while(<$Dahdi::sys_base/bus/pci/drivers/*/[0-9]*>) {
m,^(.*?)/([^/]+)/([^/]+)$,;
my $prefix = $1;
my $drvname = $2;

View File

@@ -183,6 +183,7 @@ sub scan_devices($) {
my @lines = split(/\n/);
my ($tline) = grep(/^T/, @lines);
my ($pline) = grep(/^P/, @lines);
my ($dline) = grep(/^I/, @lines);
my ($sline) = grep(/^S:.*SerialNumber=/, @lines);
my ($busnum,$devnum) = ($tline =~ /Bus=(\w+)\W.*Dev#=\s*(\w+)\W/);
my $devname = sprintf("%03d/%03d", $busnum, $devnum);
@@ -193,6 +194,10 @@ sub scan_devices($) {
$serial = $1;
#$serial =~ s/[[:^print:]]/_/g;
}
my $loaded;
if ($dline =~ /Driver=(\w+)/) {
$loaded = $1;
}
my $model = $usb_ids{"$vendor:$product"};
next unless defined $model;
my $d = Dahdi::Hardware::USB->new(
@@ -203,6 +208,7 @@ sub scan_devices($) {
SERIAL => $serial,
DESCRIPTION => $model->{DESCRIPTION},
DRIVER => $model->{DRIVER},
LOADED => $loaded,
);
push(@devices, $d);
}

View File

@@ -131,7 +131,7 @@ my @bri_strings = (
'(?:quad|octo)BRI PCI ISDN Card.* \[(NT|TE)\]',
'octoBRI \[(NT|TE)\] ',
'HFC-S PCI A ISDN.* \[(NT|TE)\] ',
'(B4XXP) \(PCI\) Card', # Does not expose NT/TE type
'(B4XXP) \(PCI\) Card', # Use dahdi_scan to determine TE/NT mode
'(WCBRI)', # has selectable NT/TE modes via dahdi_cfg
);
@@ -144,7 +144,7 @@ my @pri_strings = (
'Wildcard TE120P', # wcte12xp
'Wildcard TE121', # wcte12xp
'Wildcard TE122', # wcte12xp
'T[24]XXP \(PCI\) Card ', # wct4xxp
'T[248]XXP \(PCI\) Card ', # wct4xxp
'R[24]T1 \(PCI\) Card', # rxt1
'Rhino R1T1 (E1)/PRA Card', # r1t1
'Rhino R1T1 (T1)/PRI Card', # r1t1
@@ -177,6 +177,28 @@ sub init_proto($$) {
$self->{TYPE} = "${proto}_$self->{TERMTYPE}";
}
sub get_digital_spantype {
my $span_no = shift;
my @lines = split /\n/, `dahdi_scan`;
my $found_span = 0;
foreach my $line (@lines) {
if (! $found_span) {
if ($line =~ m/\[$span_no\]/) {
$found_span = 1;
}
} else {
if ($line !~ m/^\[/) {
if ($line =~ m/digital-(TE|NT)/ ){
return $1;
}
} else {
$found_span = 0;
}
}
}
die "Cannot determine digital spantype";
}
sub new($$) {
my $pack = shift or die "Wasn't called as a class method\n";
my $proc_file = shift or die "Missing a proc file parameter\n";
@@ -191,10 +213,16 @@ sub new($$) {
$self->{IS_DIGITAL} = 0;
$self->{IS_BRI} = 0;
$self->{IS_PRI} = 0;
$self->{TERMTYPE} = "UNKNOWN";
foreach my $cardtype (@bri_strings) {
if($head =~ m/$cardtype/) {
my $termtype = $1;
$termtype = 'TE' if ( $1 eq 'B4XXP' or $1 eq 'WCBRI' );
if ($1 eq 'B4XXP') {
$termtype = get_digital_spantype($num);
}
if ($1 eq 'WCBRI') {
$termtype = 'TE';
}
$self->{IS_DIGITAL} = 1;
$self->{IS_BRI} = 1;
$self->{TERMTYPE} = $termtype;
@@ -230,6 +258,11 @@ sub new($$) {
last;
}
}
if (($self->is_soft_term_type == 0) and ($self->termtype eq "UNKNOWN")) {
$self->{IS_SOFT_TERM_TYPE} = 1;
}
($self->{NAME}, $self->{DESCRIPTION}) = (split(/\s+/, $head, 4))[2, 3];
$self->{IS_DAHDI_SYNC_MASTER} =
($self->{DESCRIPTION} =~ /\(MASTER\)/) ? 1 : 0;
@@ -368,7 +401,7 @@ SPEC:
#print STDERR "match: $match\n";
foreach my $pattern (@patlist) {
#print STDERR "testmatch: $pattern =~ $match\n";
if($pattern =~ $match) {
if($pattern =~ /^$match$/) {
#print STDERR "MATCH '$pattern' ~ '$match' termtype=$termtype\n";
$match_termtype = $termtype;
last SPEC;

View File

@@ -29,6 +29,7 @@ set -e
# For lab testing
mydir=`dirname $0`
PATH="${mydir}:${PATH}"
XPP_WAIT_AB_TIMEOUT=80
[ -r /etc/dahdi/init.conf ] && . /etc/dahdi/init.conf
@@ -56,7 +57,7 @@ fi
# Wait for driver and first device
echo -n 1>&2 "Astribanks detection "
tries=40
tries="$XPP_WAIT_AB_TIMEOUT"
while [ ! -e "/sys/bus/astribanks/devices/xbus-00" ]
do
if [ "$tries" -le 0 ]; then

View File

@@ -70,7 +70,6 @@ ASTRIBANK_TOOL=${ASTRIBANK_TOOL:-/usr/sbin/astribank_tool}
XPP_CONFIG="${XPP_CONFIG:-/etc/dahdi/xpp.conf}"
XPP_UDEV_SLEEP_TIME="${XPP_UDEV_SLEEP_TIME:-15}"
USB_FW="${USB_FW:-USB_FW.hex}"
USB_RECOV="${USB_RECOV:-USB_RECOV.hex}"
if [ -r "$DEFAULTS" ]; then
@@ -113,6 +112,132 @@ run_fxload() {
fi
}
list_via_proc() {
cat /proc/bus/usb/devices | egrep '^P:|^T:' | sed \
-e '/^T:/s/ *Spd.*//' \
-e '/^T:/s, *Lev.*Dev#= *,\t,' \
-e '/^T:/s,Bus=,,' \
-e '/^P:/s,[A-Za-z]\+=,,g' \
-e '/^P:/s,\.,,g' | awk -vusb_prefix="$USB_PREFIX" '
/^T:/ {
bus=$2
dev=$3
}
/^P:/ {
vendor=$2
sub("0x", "", vendor);
prod=$3
sub("0x", "", product);
bcd=$4
printf("%4s/%4s/%d\t%s/%03d/%03d\n",
vendor, prod, bcd, usb_prefix, bus, dev);
}
'
}
list_via_sysfs() {
find /sys/bus/usb/devices -maxdepth 1 -mindepth 1 | \
egrep -v '/usb[0-9]|:' | while read dev; do
(
cat "$dev/idVendor"
cat "$dev/idProduct"
cat "$dev/bcdDevice"
echo "$dev" | sed \
-e 's,/sys/bus/usb/devices/,,' \
-e 's,-.*,,'
cat "$dev/devnum"
) | tr -s '\n' '\t'
echo ''
done | awk -vusb_prefix="$USB_PREFIX" '{
printf("%4s/%4s/%d\t%s/%03d/%03d\n",
$1, $2, $3, usb_prefix, $4, $5);
}'
}
list_via_lsusb() {
lsusb -v | awk -vusb_prefix="$USB_PREFIX" '
/^Bus/ {
sub(":", "", $4);
dev = sprintf("%s/%s/%s ", usb_prefix, $2, $4);
}
/idVendor/ {
id_vendor = $2
sub("0x", "", id_vendor);
}
/idProduct/ {
id_product = $2
sub("0x", "", id_product);
}
/bcdDevice/ {
bcd_device = $2
sub("^0*", "", bcd_device);
sub("[.]", "", bcd_device);
printf("%s/%s/%s\t%s\n",
id_vendor, id_product, bcd_device, dev);
}
'
}
list_devs() {
#echo >&2 "list_devs"
if [ "$#" -eq 0 ]; then
if [ -f /proc/bus/usb/devices ]; then
method='via_proc'
elif [ -d /sys/bus/usb/devices ]; then
method='via_sysfs'
else
method='via_lsusb'
fi
elif [ "$#" -eq 1 ]; then
method="$1"
else
echo >&2 "$0: unknown list_devs method='$method'"
exit 1
fi
case "$method" in
via_proc|via_sysfs|via_lsusb)
;;
*)
echo >&2 "$0: unknown list_devs method='$method'"
exit 1
;;
esac
list_$method | grep -v '^0000/0000/' | sort
}
filter_devs() {
id_str="$1"
#echo >&2 "filter_devs($id_str)"
list_devs | awk -vid_str="$id_str" '{ if ($1 ~ id_str) { print } }'
}
usb_firmware_device() {
id_str="$1"
devpath="$2"
case "$id_str" in
e4e4/11[3456]0/101|e4e4/1163/101)
fw="USB_FW.hex"
;;
e4e4/116[03]/201)
fw="USB_FW.201.hex"
;;
e4e4/*)
debug "No USB firmware for device $devpath ($id_str)"
return
;;
*)
return
;;
esac
fw_file="$FIRMWARE_DIR/$fw"
ver=$(awk '/\$Id:/ { print $4 }' $fw_file)
debug "USB Firmware $fw_file (Version=$ver) into $devpath"
run_fxload -D "$devpath" -I "$fw_file" || exit 1
}
run_astribank_hexload() {
debug "Running: $ASTRIBANK_HEXLOAD $*"
$ASTRIBANK_HEXLOAD "$@" | $LOGGER
@@ -133,18 +258,14 @@ run_astribank_tool() {
fi
}
load_usb_fw() {
v_id=$1
p_id=$2
fw=$3
devices=`find_dev $v_id $p_id`
for dev in $devices
do
ver=$(awk '/\$Id:/ { print $4 }' $FIRMWARE_DIR/$fw)
debug "USB Firmware $FIRMWARE_DIR/$fw (Version=$ver) into $dev"
run_fxload -D $dev -I $FIRMWARE_DIR/$fw || exit 1
done
usb_firmware_all_devices() {
devs=`list_devs`
echo "USB firmware"
echo "$devs" | while read id_str devpath
do
usb_firmware_device "$id_str" "$devpath"
done
wait_renumeration $numdevs 'e4e4/11[3456]1/*' "usb_firmware_all_devices"
}
load_fw_device() {
@@ -152,16 +273,18 @@ load_fw_device() {
fw="$2"
debug "FPGA loading $fw into $dev"
run_astribank_hexload -D "$dev" -F "$FIRMWARE_DIR/$fw"
if [ "$fw" = "FPGA_1161.hex" ]; then
case "$fw" in
FPGA_1161*.hex)
echo_file="$FIRMWARE_DIR/OCT6104E-256D.ima"
law=''
law_str='uLaw'
abtool_output=`$ASTRIBANK_TOOL -D "$dev" -Q 2>/dev/null`
card_type=`echo "$abtool_output" | grep '^CARD 4:' | cut -d= -f2 | cut -d. -f1`
if [ "$card_type" = '5' ]; then
abtool_output=`$ASTRIBANK_TOOL -D "$dev" -Q 2>&1`
ec_card_type=`echo "$abtool_output" | grep 'CARD 4' | sed -e 's/.*type=//' -e 's/\..*//'`
caps_num=`echo "$abtool_output" | grep 'ECHO ports' | sed -e 's/.*: *//'`
if [ "$ec_card_type" = '5' ]; then
debug "ECHO burning into $dev: $echo_file"
card_type_first=`echo "$abtool_output" | grep '^CARD 0:' | cut -d= -f2 | cut -d. -f1`
case "$card_type_first" in
card_type=`echo "$abtool_output" | grep 'CARD 0' | sed -e 's/.*type=//' -e 's/\..*//'`
case "$card_type" in
3) law="-A";;
4)
pri_protocol=''
@@ -182,88 +305,116 @@ load_fw_device() {
if [ "$caps_num" != '0' ]; then
run_astribank_hexload -D "$dev" -O $law "$echo_file"
else
$LOGGER "WARNING: ECHO burning was skipped (no capabilities)"
echo "WARNING: ECHO burning was skipped (no capabilities)"
fi
fi
pic_files=`echo "$FIRMWARE_DIR"/PIC_TYPE_[1-4].hex`
debug "PIC burning into $dev: $pic_files"
debug "PIC burning into $dev: begin $pic_files"
run_astribank_hexload -D "$dev" -p $pic_files
debug "PIC burning finished $pic_files"
fi
debug "PIC burning into $dev: end $pic_files"
;;
esac
# Do renumeration!
run_astribank_tool -D "$dev" -n > /dev/null
debug "Reenumeration done."
run_astribank_tool -D "$dev" -n > /dev/null 2>&1
debug "Renumeration of $dev done."
}
#
# Use in manual loading. Parallelize loading
# firmwares to all of our devices
#
firmware_by_id() {
v_id=$1
p_id=$2
fw=$3
devices=`find_dev $v_id $p_id`
childs=""
for dev in $devices
do
(
set -e
fpga_firmware_device() {
id_str="$1"
devpath="$2"
load_fw_device "$dev" "$fw"
id_product=`echo "$id_str" | cut -d/ -f2`
bcd_device=`echo "$id_str" | cut -d/ -f3`
case "$id_str" in
e4e4/1131/101)
fw="FPGA_FXS.hex"
;;
e4e4/11[456]1/101)
fw="FPGA_${id_product}.hex"
;;
e4e4/1161/201)
fw="FPGA_${id_product}.${bcd_device}.hex"
;;
e4e4/*)
debug "No FPGA firmware for device $devpath ($id_str)"
return
;;
*)
return
;;
esac
debug "Loading $fw into $devpath"
load_fw_device "$devpath" "$fw"
sleep_if_race
) &
childs="$childs $!"
sleep 0.4
done
# Wait for specific childs to get their exit status
wait $childs
}
numdevs() {
v_ids="$1"
p_ids="$2"
id_str="$1"
for v in $v_ids
do
(
for p in $p_ids
do
find_dev $v $p
done
)
done | wc -w
#echo >&2 "numdevs($id_str)"
filter_devs "$id_str" | wc -l
}
wait_renumeration() {
num="$1"
v_ids="$2"
p_ids="$3"
num="$1"
id_str="$2"
caller="$3"
iter=10
while
n=`numdevs "$v_ids" "$p_ids"`
[ "$num" -gt "$n" ]
do
echo -n "."
sleep 1
done
echo "Got all $num devices"
prev=0
echo "Waiting renumeration ($caller)"
while
n=`numdevs "$id_str"`
[ "$num" -gt "$n" ]
do
if [ "$prev" -lt "$n" ]; then
echo -n "+"
else
echo -n "."
fi
sleep 1
prev="$n"
debug "wait($iter) (found $n from $num devices) ($caller)"
if ! iter=`expr $iter - 1`; then
echo "Timeout (found $n from $num devices) ($caller)"
break;
fi
done
echo "Got all $num devices ($caller)"
sleep 1 # Let everything settle
}
fpga_firmware_all_devices() {
echo "Loading FPGA firmwares" | $LOGGER
devs=`filter_devs 'e4e4/11[3456]1/*'`
n=`echo "$devs" | wc -l`
echo "$devs" | (
while read id_str devpath; do
fpga_firmware_device "$id_str" "$devpath" &
done
sleep 1
echo "Wait for FPGA loading processes"
wait
) 2>&1 | $LOGGER
wait_renumeration $numdevs 'e4e4/11[3456]2/*' "fpga_firmware_device"
}
reset_fpga() {
totaldevs=`numdevs e4e4 '11[3456][0123]'`
devices=`find_dev e4e4 '11[3456][12]'`
debug "Reseting devices [$totaldevs devices]"
for dev in $devices
do
debug "Resetting FPGA Firmware on $dev"
sleep_if_race
run_astribank_tool -D "$dev" -r full 2>&1 >/dev/null
done
if [ "$1" = 'wait' ]; then
wait_renumeration $totaldevs e4e4 '11[3456][03]'
fi
devices=`filter_devs 'e4e4/11[3456][124]/*'`
totaldevs=`numdevs 'e4e4/11[3456][124]/*'`
$LOGGER -- "Reseting devices [$totaldevs devices]"
echo "$devices" | grep -v '^$' | while read id_str dev
do
(
debug "Resetting FPGA Firmware on $dev"
sleep_if_race
run_astribank_tool -D "$dev" -r full >/dev/null 2>&1
) &
done
wait
if [ "$1" = 'wait' ]; then
wait_renumeration $totaldevs 'e4e4/11[3456][03]/*' "reset_fpga"
fi
}
usage() {
@@ -304,29 +455,28 @@ reset-wait)
reset)
reset_fpga
;;
list)
filter_devs 'e4e4/*/*'
exit 0
;;
xppdetect|load|usb)
numdevs=`numdevs e4e4 '11[3456][013]'`
numdevs=`numdevs 'e4e4/11[3456][0134]/*'`
$LOGGER -- "--------- FIRMWARE LOADING: ($1) [$numdevs devices]"
load_usb_fw e4e4 1130 $USB_FW
load_usb_fw e4e4 1140 $USB_FW
load_usb_fw e4e4 1150 $USB_FW
load_usb_fw e4e4 1160 $USB_FW
load_usb_fw e4e4 1163 $USB_FW
wait_renumeration $numdevs e4e4 '11[3456]1'
usb_firmware_all_devices 2>&1 | $LOGGER
if [ "$1" != 'usb' ]
then
firmware_by_id e4e4 1131 FPGA_FXS.hex
firmware_by_id e4e4 1141 FPGA_1141.hex
firmware_by_id e4e4 1151 FPGA_1151.hex
firmware_by_id e4e4 1161 FPGA_1161.hex
wait_renumeration $numdevs e4e4 '11[3456]2'
fpga_firmware_all_devices
fi
sleep 3 # Let it stabilize
$LOGGER -- "--------- FIRMWARE IS LOADED"
exit 0
;;
recover-sb)
# Load a firmware that fixes a but which makes the Source Byte in the
# EEPROM reset and make the device appear like a Cypress dev kit:
load_usb_fw 04b4 8613 $USB_RECOV
;;
help)
usage
exit 0
@@ -379,27 +529,28 @@ udev_delayed_load() {
fi
$LOGGER "Trying to find what to do for product $PRODUCT, device $DEVICE"
prod_id=`echo "$PRODUCT" | cut -d/ -f2`
case "$PRODUCT" in
e4e4/11[3456]0/*|e4e4/1163/*)
FIRM_USB="$FIRMWARE_DIR/$USB_FW"
$LOGGER "Loading firmware '$FIRM_USB' into '$DEVICE'"
4b4/8613/*)
# This case is for a potentially-broken Astribank.
# In most systems you should not set udev rules for those to
# get here, as this is actually the ID of a Cypress dev-kit:
FIRM_USB="$FIRMWARE_DIR/$USB_RECOV"
$LOGGER "Loading recovery firmware '$FIRM_USB' into '$DEVICE'"
run_fxload -D "$DEVICE" -I "$FIRM_USB"
;;
e4e4/11[3456]0/*|e4e4/1163/*)
usb_firmware_device "$PRODUCT" "$DEVICE"
;;
e4e4/11[3456]1/*)
# There are potentially two separate udev events, for
# each of the two endpoints. Ignore the first interface:
case "$DEVPATH" in *.0) exit 0;; esac
if [ "$prod_id" = 1131 ]; then
FIRM_FPGA="FPGA_FXS.hex" # Legacy
else
FIRM_FPGA="FPGA_$prod_id.hex"
fi
sleep_if_race
load_fw_device "$DEVICE" "$FIRM_FPGA"
fpga_firmware_device "$PRODUCT" "$DEVICE" &
wait # parallel firmware loading
;;
esac
}
udev_delayed_load &
udev_delayed_load 2>&1 | $LOGGER &

View File

@@ -30,11 +30,16 @@
#include <arpa/inet.h>
#include <debug.h>
#include <xusb.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
static const char rcsid[] = "$Id$";
#define DBG_MASK 0x01
#define TIMEOUT 500
#define MAX_RETRIES 10
struct xusb {
struct usb_device *dev;
@@ -56,6 +61,8 @@ struct xusb {
size_t packet_size;
};
static void xusb_init();
void xusb_init_spec(struct xusb_spec *spec, char *name,
uint16_t vendor_id, uint16_t product_id,
int nifaces, int iface, int nep, int ep_out, int ep_in)
@@ -363,9 +370,7 @@ struct xusb *xusb_find_iface(const char *devpath, int iface_num, int ep_out, int
struct usb_bus *bus;
DBG("\n");
usb_init();
usb_find_busses();
usb_find_devices();
xusb_init();
for (bus = usb_get_busses(); bus; bus = bus->next) {
int bus_num;
char tmppath[PATH_MAX + 1];
@@ -477,9 +482,7 @@ struct xlist_node *xusb_find_byproduct(const struct xusb_spec *specs, int numspe
ERR("Failed allocation new xlist");
goto fail_xlist;
}
usb_init();
usb_find_busses();
usb_find_devices();
xusb_init();
for (bus = usb_get_busses(); bus; bus = bus->next) {
for (dev = bus->devices; dev; dev = dev->next) {
struct usb_device_descriptor *dev_desc;
@@ -540,7 +543,10 @@ struct xusb *xusb_open_one(const struct xusb_spec *specs, int numspecs, xusb_fil
xusb = curr->data;
xlist_destroy(curr, NULL);
xlist_destroy(xusb_list, NULL);
xusb_claim_interface(xusb);
if(!xusb_claim_interface(xusb)) {
xusb_destroy(xusb);
return NULL;
}
xusb_showinfo(xusb);
break;
default:
@@ -657,12 +663,14 @@ int xusb_close(struct xusb *xusb)
int xusb_send(struct xusb *xusb, char *buf, int len, int timeout)
{
int ret;
int retries = 0;
dump_packet(LOG_DEBUG, DBG_MASK, __FUNCTION__, buf, len);
if(EP_OUT(xusb) & USB_ENDPOINT_IN) {
ERR("%s called with an input endpoint 0x%x\n", __FUNCTION__, EP_OUT(xusb));
return -EINVAL;
}
retry_write:
ret = usb_bulk_write(xusb->handle, EP_OUT(xusb), buf, len, timeout);
if(ret < 0) {
/*
@@ -672,17 +680,39 @@ int xusb_send(struct xusb *xusb, char *buf, int len, int timeout)
if(ret != -ENODEV) {
ERR("bulk_write to endpoint 0x%x failed: (%d) %s\n",
EP_OUT(xusb), ret, usb_strerror());
dump_packet(LOG_ERR, DBG_MASK, "xbus_send[ERR]", buf, len);
dump_packet(LOG_ERR, DBG_MASK, "xusb_send[ERR]", buf, len);
//exit(2);
} else {
DBG("bulk_write to endpoint 0x%x got ENODEV\n", EP_OUT(xusb));
xusb_close(xusb);
}
return ret;
} else if(ret != len) {
}
if(!ret) {
#if 0
FILE *fp;
fp = fopen("/tmp/xusb.log", "a");
if (!fp) {
ERR("%s: Failed writing to /tmp/xusb.log\n", __func__);
return -EFAULT;
}
fprintf(fp, "[%ld] bulk_write to endpoint 0x%x short write[%d]: (%d)\n",
time(NULL), EP_OUT(xusb), retries, ret);
fclose(fp);
#endif
ERR("bulk_write to endpoint 0x%x short write[%d]: (%d)\n",
EP_OUT(xusb), retries, ret);
if (retries++ > MAX_RETRIES) {
return -EFAULT;
}
usleep(100);
goto retry_write;
}
if(ret != len) {
ERR("bulk_write to endpoint 0x%x short write: (%d) %s\n",
EP_OUT(xusb), ret, usb_strerror());
dump_packet(LOG_ERR, DBG_MASK, "xbus_send[ERR]", buf, len);
dump_packet(LOG_ERR, DBG_MASK, "xusb_send[ERR]", buf, len);
return -EFAULT;
}
return ret;
@@ -691,11 +721,13 @@ int xusb_send(struct xusb *xusb, char *buf, int len, int timeout)
int xusb_recv(struct xusb *xusb, char *buf, size_t len, int timeout)
{
int ret;
int retries = 0;
if(EP_IN(xusb) & USB_ENDPOINT_OUT) {
ERR("%s called with an output endpoint 0x%x\n", __FUNCTION__, EP_IN(xusb));
return -EINVAL;
}
retry_read:
ret = usb_bulk_read(xusb->handle, EP_IN(xusb), buf, len, timeout);
if(ret < 0) {
DBG("bulk_read from endpoint 0x%x failed: (%d) %s\n",
@@ -703,6 +735,27 @@ int xusb_recv(struct xusb *xusb, char *buf, size_t len, int timeout)
memset(buf, 0, len);
return ret;
}
if(!ret) {
#if 0
FILE *fp;
fp = fopen("/tmp/xusb.log", "a");
if (!fp) {
ERR("%s: Failed writing to /tmp/xusb.log\n", __func__);
return -EFAULT;
}
fprintf(fp, "[%ld] bulk_read from endpoint 0x%x short read[%d]: (%d)\n",
time(NULL), EP_IN(xusb), retries, ret);
fclose(fp);
#endif
ERR("bulk_read to endpoint 0x%x short read[%d]: (%d)\n",
EP_IN(xusb), retries, ret);
if (retries++ > MAX_RETRIES) {
return -EFAULT;
}
usleep(100);
goto retry_read;
}
dump_packet(LOG_DEBUG, DBG_MASK, __FUNCTION__, buf, ret);
return ret;
}
@@ -724,3 +777,74 @@ int xusb_flushread(struct xusb *xusb)
}
return 0;
}
/*
* Serialize calls to usb_find_busses()/usb_find_devices()
*/
static const key_t SEM_KEY = 0x1a2b3c4d;
static int semid = -1; /* Failure */
static void xusb_lock_usb()
{
struct sembuf sembuf;
while (semid < 0) {
/* Maybe it was already created? */
semid = semget(SEM_KEY, 1, 0);
if (semid < 0) {
/* No, let's create ourselves */
semid = semget(SEM_KEY, 1, IPC_CREAT | IPC_EXCL | 0644);
if (semid < 0) {
/* Someone else won the race to create it */
if (errno != ENOENT)
ERR("%s: semget() failed: %s\n",
__func__, strerror(errno));
/* Retry */
continue;
}
/* Initialize */
if (semctl(semid, 0, SETVAL, 1) < 0)
ERR("%s: SETVAL() failed: %s\n",
__func__, strerror(errno));
}
}
DBG("%d: LOCKING\n", getpid());
sembuf.sem_num = 0;
sembuf.sem_op = -1;
sembuf.sem_flg = SEM_UNDO;
if (semop(semid, &sembuf, 1) < 0) {
ERR("%s: semop() failed: %s\n", __func__, strerror(errno));
}
DBG("%d: LOCKED\n", getpid());
}
static void xusb_unlock_usb()
{
struct sembuf sembuf;
DBG("%d: UNLOCKING\n", getpid());
sembuf.sem_num = 0;
sembuf.sem_op = 1;
sembuf.sem_flg = SEM_UNDO;
if (semop(semid, &sembuf, 1) < 0) {
ERR("%s: semop() failed: %s\n", __func__, strerror(errno));
}
DBG("%d: UNLOCKED\n", getpid());
}
static int initizalized = 0;
static void xusb_init()
{
if (!initizalized) {
if (!getenv("XUSB_NOLOCK"))
xusb_lock_usb();
usb_init();
usb_find_busses();
usb_find_devices();
initizalized = 1;
if (!getenv("XUSB_NOLOCK"))
xusb_unlock_usb();
}
}