summaryrefslogtreecommitdiff
path: root/xpp/utils
diff options
context:
space:
mode:
Diffstat (limited to 'xpp/utils')
-rw-r--r--xpp/utils/Makefile17
-rw-r--r--xpp/utils/adj_clock.8144
-rw-r--r--xpp/utils/adj_clock.c228
-rw-r--r--xpp/utils/fpga_load.822
-rw-r--r--xpp/utils/fpga_load.c217
-rwxr-xr-xxpp/utils/genzaptelconf85
-rw-r--r--xpp/utils/hexfile.c74
-rw-r--r--xpp/utils/hexfile.h1
-rwxr-xr-xxpp/utils/lszaptel4
-rwxr-xr-xxpp/utils/xpp_blink115
-rw-r--r--xpp/utils/xpp_fxloader34
-rwxr-xr-xxpp/utils/xpp_sync42
-rw-r--r--xpp/utils/zconf/Zaptel.pm5
-rw-r--r--xpp/utils/zconf/Zaptel/Chans.pm38
-rw-r--r--xpp/utils/zconf/Zaptel/Span.pm58
-rw-r--r--xpp/utils/zconf/Zaptel/Xpp.pm17
-rw-r--r--xpp/utils/zconf/Zaptel/Xpp/Xbus.pm36
-rw-r--r--xpp/utils/zconf/Zaptel/Xpp/Xpd.pm31
-rwxr-xr-xxpp/utils/zt_registration19
19 files changed, 645 insertions, 542 deletions
diff --git a/xpp/utils/Makefile b/xpp/utils/Makefile
index a49818b..96b37db 100644
--- a/xpp/utils/Makefile
+++ b/xpp/utils/Makefile
@@ -46,12 +46,12 @@ CFLAGS = -g -Wall $(EXTRA_CFLAGS)
%.8: %
pod2man --section 8 $^ > $@ || $(RM) $@
-PERL_SCRIPTS = zt_registration xpp_sync lszaptel
-PERL_MANS = zt_registration.8 xpp_sync.8 lszaptel.8
+PERL_SCRIPTS = zt_registration xpp_sync lszaptel xpp_blink
+PERL_MANS = $(PERL_SCRIPTS:%=%.8)
-TARGETS = init_fxo_modes print_modes adj_clock
-PROG_INSTALL = genzaptelconf adj_clock
-MAN_INSTALL = genzaptelconf.8 adj_clock.8
+TARGETS = init_fxo_modes print_modes
+PROG_INSTALL = genzaptelconf
+MAN_INSTALL = genzaptelconf.8
ifeq (1,$(PBX_LIBUSB))
TARGETS += libhexfile.a fpga_load test_parse
PROG_INSTALL += fpga_load
@@ -60,17 +60,14 @@ endif
ifneq (,$(PERLLIBDIR))
PROG_INSTALL += $(PERL_SCRIPTS)
MAN_INSTALL += $(PERL_MANS)
+TARGETS += $(PERL_MANS)
endif
all: $(TARGETS)
docs: $(PERL_MANS)
-# give an ugly warning if Timer::Hires is missing:
-sanity_checks:
- perl -c ../calibrate_slics >/dev/null || true
-
-install: all sanity_checks
+install: all
$(INSTALL) -d $(DESTDIR)$(SBINDIR)
$(INSTALL) $(PROG_INSTALL) $(DESTDIR)$(SBINDIR)/
$(INSTALL) -d $(DESTDIR)$(DATADIR)
diff --git a/xpp/utils/adj_clock.8 b/xpp/utils/adj_clock.8
deleted file mode 100644
index 0e9cf71..0000000
--- a/xpp/utils/adj_clock.8
+++ /dev/null
@@ -1,144 +0,0 @@
-." $Id:$
-.TH adj_clock 8 "2006-10-18"
-.SH "NAME"
-adj_clock \(em Synchronize system clock to zaptel clock
-.SH "SYNOPSIS"
-.B adj_clock
-.I [ -c
-.B count
-.I ] [ -i
-.B interval
-.I ] [ -t
-.B period
-.I ] [ -v ]
-
-.SH "DESCRIPTION"
-.B adj_clock
-compares synchronizes the system clock from Zaptel's clock: in each cycle
-It will read 1024 *
-.B interval
-ticks from a Zaptel pseudo channel, which should take exactly
-.B interval
-seconds. It measures the time it did take, and uses
-.I adjtimex(3)
-to fix the system clock accordingly.
-
-Note that NTP servers usually use adjtimex. You may get strange behaviour
-if you have a NTP server (such as ntpd(8)) running on the system.
-
-Output is sent to both the standard error and to the syslog. Syslog
-messages are with facility daemon.
-
-.SH OPTIONS
-.I -c
-.B count
-.RS
-Run just
-.B count
-synchronization cycles. Default is to run forever.
-.RE
-
-.I -i
-.B interval
-.RS
-Loop interval (in seconds). Optional, as program should provide a sane value.
-
-Small values allow faster synchronization when the system is quiet. Even
-a value as low as 10 should work. However they are much more suspectable
-to short interruptions.
-
-.RE
-
-.I -t
-.B period
-.RS
-Set the synchronization tolerance priod (micro-seconds). The default
-is 100. Don't touch it unless you know what you're doing.
-.RE
-
-.I -v
-.RS
-Be more verbose: log status messages even when synchronized.
-.RE
-
-.SH FILES
-.B /dev/zap/pseudo
-.RS
-.RE
-The device file used to open a "pseudo" channel (a channels that
-constantly streams voice and is synchronized by the master Zaptel
-device).
-
-.SH SYNCHRONIZATION
-Some more technical details. This explains the strange numbers the
-program prints.
-
-In each cycle
-.B adj_clock
-measures
-.B interval
-seconds using Zaptel ticks. It then compares that to the system time
-from gettimeofday(2). It then calls adjtimex(2) to slightly change the
-rate of the system clock. It uses two parameters:
-.B ticks,
-which is a more
-coarse one (1 tick will give roughly a change of rate of 9 seconds per
-day) and
-.I frequency,
-which allows much finer settings.
-
-The program tries to set what it can by ticks, and the rest through
-frequency. It considers itself "synchronized" when the rate difference
-is small enough so
-.I (a)
-It does not have to use ticks anymore. And
-.I (b)
-The rest of the interval to change is smaller than the tolerance period
-(100 micro-seconds, by default).
-
-The meaning of the parameters it prints is, thus:
-
-.I interval
-.RS
-The current interval parameter (seconds).
-.RE
-
-.I diff_tick
-.RS
-The number of ticks it tries to set through adjtimex(2).
-Anything different than 0 means we're still way off mark.
-.RE
-
-.I diff_usec
-.RS
-The time difference (micro-seconds) that we need to overcome in the
-first place. This is the difference between the system clock and the
-measured zaptel clock.
-.RE
-
-.I usec_left
-.RS
-How much of this difference (microseconds) we still need to adjust
-after using ticks. This should be low enough (less than the tolerance
-period).
-.RE
-
-.SH SIGNALS
-.B adj_clock
-is so far an interactive program, and thus killed by SIGHUP. SIGUSR is
-used to increase verbosity level and SIGUSR2 is used to reset verbosity
-level to 0. When SIGUSR1 is recieved a status message will also be sent
-to the logs.
-
-.SH SEE ALSO
-ztcfg(8), zttest(8), adjtimex(2), gettimeofday(2), adjtimex(8)
-
-.SH AUTHOR
-
-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.
-
-On Debian systems, the complete text of the GNU General Public
-License can be found in /usr/share/common-licenses/GPL.
diff --git a/xpp/utils/adj_clock.c b/xpp/utils/adj_clock.c
deleted file mode 100644
index 6dfa483..0000000
--- a/xpp/utils/adj_clock.c
+++ /dev/null
@@ -1,228 +0,0 @@
-/*
- * Written by Tzafrir Cohen <tzafrir.cohen@xorcom.com>
- * Copyright (C) 2006, Xorcom
- *
- * Derived from zttest.c
- *
- * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- */
-#include <sys/timex.h>
-#include <linux/param.h>
-#include <syslog.h>
-#include <stdio.h>
-#include <unistd.h>
-#include <stdlib.h>
-#include <string.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <sys/time.h>
-#include <sys/signal.h>
-#include <math.h>
-
-static const char *rcsid = "$Id$";
-
-#define FREQ_PER_TICK (64*1024)
-#define USEC_PER_ZAP_TICK 1000 /* Zaptel tick in usec */
-#define USER_HZ 100
-#define SYNC_TOLERANCE 100
-#define DEFAULT_INTERVAL 60
-
-static const char *program;
-static int synced_time; /* time (seconds) we are so far synced */
-static int verbose = 0;
-static int sync_tolerance = 100;
-
-void usage() {
- fprintf(stderr, "%s: synchronize system clock from zaptel clock.\n"
- "Version: %s\n"
- "\n"
- "Usage: %s [ -c COUNT ] [-i INTERVAL] [ -t PERIOD ] [-v]\n"
- " %s -h\n"
- "\n"
- "Options:\n"
- " -c only run COUNT cycles of synchronization (default: forever).\n"
- " -i set cycle Interval to INTERVAL (in seconds. Default: %d).\n"
- " -t sync tolerance to PERIOD (in usec. Default: %d). For debugging.\n"
- " -v Be more Verbose\n"
- " -h Print this Help text and exit.\n"
- "", program, rcsid, program, program, DEFAULT_INTERVAL,
- sync_tolerance);
-}
-
-/* based on zttest.c */
-
-/*
- * Print a message to the log according to the value of synced_time
- *
- * All parameters are for the "Not Synced" warning message.
- * TODO: Find a better way.
- */
-void status_message(void) {
- if (synced_time == 0)
- syslog(LOG_NOTICE, "Not Synced.\n");
- else
- syslog(LOG_INFO, "Good Sync for %d seconds\n", synced_time);
-
- return;
-}
-
-/*
- * interval: period, in seconds
- * diff_usec: Current offset, in micro-seconds.
- */
-int clock_sync(int interval, int diff_usec)
-{
- struct timex cur_time = {.modes=0}; /* just query */
- int diff_tick; /* Difference in adjtimex ticks */
- int req_tick; /* Required adjtimex tick value */
- long long diff_freq;
- long long req_freq;
- int usec_left; /* Usec adjusted by frequency */
- int ret;
-
- ret = adjtimex(&cur_time);
-
- diff_tick = diff_usec / (interval * USER_HZ);
- usec_left = diff_usec - diff_tick * (interval * USER_HZ);
- diff_freq = usec_left * FREQ_PER_TICK / interval;
-
- req_tick = cur_time.tick - diff_tick;
- req_freq = cur_time.freq - diff_freq;
-
- if(!diff_tick && abs(usec_left) < sync_tolerance)
- synced_time += interval;
- else
- synced_time = 0;
- status_message();
- if (verbose || !synced_time)
- syslog(LOG_INFO, "interval: %d, diff_tick: %d, diff_usec: %d, usec_left: %d.\n",
- interval, diff_tick, diff_usec, usec_left);
-
- /* set the clock rate */
- cur_time.freq = req_freq;
- cur_time.tick = req_tick;
- cur_time.modes = ADJ_TICK | ADJ_FREQUENCY;
- ret = adjtimex(&cur_time);
- if (ret < 0)
- syslog(LOG_ERR, "Adjtimex failed to set frequency. New frequency: %lld. Error: %d (%s)\n",
- req_freq, errno, strerror(errno));
- return 0;
-}
-
-static int pass = 0;
-
-void hup_handler(int sig)
-{
- if (verbose > 0) {
- syslog(LOG_INFO, "--- Results after %d passes ---\n", pass);
- status_message();
- }
- closelog();
- exit(0);
-}
-
-void sigusr1_handler(int sig) {
- verbose++;
- syslog(LOG_INFO, "Increased verbosity to %d (increase: SIGUSR1, reset: SIGUSR2).\n", verbose);
- status_message();
-}
-
-void sigusr2_handler(int sig) {
- verbose = 0;
- syslog(LOG_INFO, "Set verbosity to 0 (increase: SIGUSR1, reset: SIGUSR2).\n");
-}
-
-void sync_cycle(int fd, int interval)
-{
- char buf[1024]; /* TODO: why 1024 and not 1000? */
- struct timeval start;
- struct timeval end;
- long long usec;
- int count = 0;
- int i;
- int res;
-
- gettimeofday(&start, NULL);
- for (i=0; i < interval*8; i++) {
- res = read(fd, buf, sizeof(buf));
- if (res < 0) {
- syslog(LOG_ERR, "Failed to read from pseudo interface: %s\n", strerror(errno));
- exit(1);
- }
- count += res/8;
- }
- gettimeofday(&end, NULL);
-
- /* time difference in microseconds: */
- usec = (end.tv_sec - start.tv_sec) * 1000000;
- usec += end.tv_usec - start.tv_usec;
-
- clock_sync(interval, usec - (count * USEC_PER_ZAP_TICK));
-
- pass++;
-}
-
-int main(int argc, char *argv[])
-{
- int fd;
- int opt;
- int interval = DEFAULT_INTERVAL;
- int cycles_to_run = 0;
- int i;
-
- program = argv[0];
- while((opt = getopt(argc, argv, "c:hi:t:v")) != -1) {
- switch (opt) {
- case 'h': usage(); exit(0); break;
- case 'c': cycles_to_run = atoi(optarg); break;
- case 'i': interval = atoi(optarg); break; /* number of seconds */
- case 't': sync_tolerance = atoi(optarg); break; /* usec */
- case 'v': verbose++; break;
- default:
- fprintf(stderr, "%s: Unknown option: %c. Aborting\n", argv[0], opt);
- usage();
- exit(1);
- }
- }
-
- openlog(program, LOG_PERROR | LOG_PID, LOG_DAEMON);
- fd = open("/dev/zap/pseudo", O_RDWR);
- if (fd < 0) {
- fprintf(stderr, "Unable to open zap interface: %s\n", strerror(errno));
- exit(1);
- }
- if (verbose >=1)
- syslog(LOG_INFO, "Opened pseudo zap interface, measuring accuracy...\n");
-
- signal(SIGHUP, hup_handler);
- signal(SIGINT, hup_handler);
- signal(SIGUSR1, sigusr1_handler);
- signal(SIGUSR2, sigusr2_handler);
-
- if (cycles_to_run > 0) {
- for(i=0; i<cycles_to_run; i++) {
- sync_cycle(fd, interval);
- }
- hup_handler(0); /* exit */;
- }
-
- /* else (option -c not provided): run forever. */
- for(;;) {
- sync_cycle(fd, interval);
- }
-}
diff --git a/xpp/utils/fpga_load.8 b/xpp/utils/fpga_load.8
index 640bbfd..412a839 100644
--- a/xpp/utils/fpga_load.8
+++ b/xpp/utils/fpga_load.8
@@ -5,10 +5,10 @@ ztcfg \- reads and loads zaptel.conf
.SH SYNOPSIS
.B fpga_load
-[\fB-g\fR] [\fB-v\fR] \fB-D \fR{/proc/bus/usb|/dev/bus/usb}/\fIBUS/DEV\fR
+[\fB-g\fR] [\fB-r\fR] [\fB-v\fR] \fB-D \fR{/proc/bus/usb|/dev/bus/usb}/\fIBUS/DEV\fR
.B fpga_load
-[\fB-g\fR] [\fB-v\fR] \fB-D \fR{/proc/bus/usb|/dev/bus/usb}/\fIBUS/DEV\fR \fB-I \fIfirmware.hex\fR [\fB-b \fIdump.bin\fR]
+[\fB-g\fR] [\fB-v\fR] \fB-D \fR{/proc/bus/usb|/dev/bus/usb}/\fIBUS/DEV\fR \fB-I \fIfirmware.hex\fR [\fB-b \fIdump.bin\fR] [\fB-i\fR]
.B fpga_load -h
@@ -36,6 +36,11 @@ On older systems that use usbfs, it is usually
/proc/bus/usb/\fIbus_num\fR/\fIdevice_num\fR.
.RE
+.B -r
+.RS
+Reset the Astribank and renumerate its USB connection to power on product ID.
+.RE
+
.B -g
.RS
Dump all eeprom data to standard output.
@@ -47,9 +52,20 @@ Dump all eeprom data to standard output.
The firmware file to write to the device.
.RE
+.B -i
+.RS
+Show information about the firmware file (valid only with \fB-I\fR option).
+Example:
+.PP
+ ./FPGA_1151.hex: Version=3297 Checksum=58270
+
+In particular, the calculated checksum should match the output of \fIsum(1)\fR
+on the binary firmware file generated by the \fB-b\fR option.
+.RE
+
.B -v
.RS
-Be verobse.
+Increase verbosity. May be used multiple times.
.RE
.B -h
diff --git a/xpp/utils/fpga_load.c b/xpp/utils/fpga_load.c
index 2c03704..1cbd749 100644
--- a/xpp/utils/fpga_load.c
+++ b/xpp/utils/fpga_load.c
@@ -12,8 +12,8 @@ static const char rcsid[] = "$Id$";
#define ERR(fmt, arg...) do { \
if(verbose >= LOG_ERR) \
- fprintf(stderr, "%s: ERROR: " fmt, \
- progname, ## arg); \
+ fprintf(stderr, "%s: ERROR (%d): " fmt, \
+ progname, __LINE__, ## arg); \
} while(0);
#define INFO(fmt, arg...) do { \
if(verbose >= LOG_INFO) \
@@ -35,14 +35,15 @@ static char *progname;
#define SERIAL_SIZE 8
enum fpga_load_packet_types {
- STATUS_REPLY = 0x01,
- DATA_PACKET = 0x01,
+ PT_STATUS_REPLY = 0x01,
+ PT_DATA_PACKET = 0x01,
#ifdef XORCOM_INTERNAL
- EEPROM_SET = 0x04,
+ PT_EEPROM_SET = 0x04,
#endif
- EEPROM_GET = 0x08,
- RENUMERATE = 0x10,
- BAD_COMMAND = 0xAA
+ PT_EEPROM_GET = 0x08,
+ PT_RENUMERATE = 0x10,
+ PT_RESET = 0x20,
+ PT_BAD_COMMAND = 0xAA
};
struct myeeprom {
@@ -173,8 +174,8 @@ int get_usb_string(char *buf, unsigned int len, uint16_t item, usb_dev_handle *h
}
/* My device parameters */
-#define MY_INTERFACE 0
#define MY_CONFIG 1
+#define MY_INTERFACE 0
#define MY_ENDPOINTS 4
#define MY_EP_OUT 0x04
@@ -186,10 +187,10 @@ int get_usb_string(char *buf, unsigned int len, uint16_t item, usb_dev_handle *h
#define TIMEOUT 5000
static const int my_endpoints[MY_ENDPOINTS] = {
- 0x02,
- 0x04,
- 0x86,
- 0x88
+ FPGA_EP_OUT,
+ MY_EP_OUT,
+ FPGA_EP_IN,
+ MY_EP_IN
};
void my_usb_device_cleanup(struct my_usb_device *mydev)
@@ -226,12 +227,47 @@ static void show_device_info(const struct my_usb_device *mydev)
data[4], data[5], data[6], data[7]);
}
-void dump_packet(const char *buf, int len)
+void dump_packet(const char *msg, const char *buf, int len)
{
int i;
for(i = 0; i < len; i++)
- INFO("dump: %2d> 0x%02X\n", i, (uint8_t)buf[i]);
+ INFO("%s: %2d> 0x%02X\n", msg, i, (uint8_t)buf[i]);
+}
+
+int send_usb(const char *msg, struct my_usb_device *mydev, int endpoint, struct fpga_packet_header *phead, int len, int timeout)
+{
+ char *p = (char *)phead;
+ int ret;
+
+ if(verbose >= LOG_DEBUG)
+ dump_packet(msg, p, len);
+ ret = usb_bulk_write(mydev->handle, endpoint, p, len, timeout);
+ if(ret < 0) {
+ ERR("bulk_write failed: %s\n", usb_strerror());
+ dump_packet("send_usb[ERR]", p, len);
+ return ret;
+ } else if(ret != len) {
+ ERR("bulk_write short write: %s\n", usb_strerror());
+ dump_packet("send_usb[ERR]", p, len);
+ return -EFAULT;
+ }
+ return ret;
+}
+
+int recv_usb(const char *msg, struct my_usb_device *mydev, int endpoint, char *buf, size_t len, int timeout)
+{
+ int ret;
+
+ if(verbose >= LOG_DEBUG)
+ dump_packet(msg, buf, len);
+ ret = usb_bulk_read(mydev->handle, endpoint, buf, len, timeout);
+ if(ret < 0) {
+ ERR("bulk_read failed: %s\n", usb_strerror());
+ dump_packet("recv_usb[ERR]", buf, len);
+ return ret;
+ }
+ return ret;
}
#ifdef XORCOM_INTERNAL
@@ -244,39 +280,23 @@ int eeprom_set(struct my_usb_device *mydev, const struct myeeprom *eeprom)
DBG("%s Start...\n", __FUNCTION__);
assert(mydev != NULL);
- phead->header.op = EEPROM_SET;
+ phead->header.op = PT_EEPROM_SET;
memcpy(&phead->d.eeprom_set.data, eeprom, EEPROM_SIZE);
len = sizeof(phead->d.eeprom_set) + sizeof(phead->header.op);
- if(verbose >= LOG_DEBUG) {
- DBG("%s write %d bytes\n", __FUNCTION__, len);
- dump_packet((char *)phead, len);
- }
- ret = usb_bulk_write(mydev->handle, MY_EP_OUT, (char *)phead, len, TIMEOUT);
- if(ret < 0) {
- ERR("bulk_write failed: %s\n", usb_strerror());
+ ret = send_usb("eeprom_set[W]", mydev, MY_EP_OUT, phead, len, TIMEOUT);
+ if(ret < 0)
return ret;
- } else if(ret != len) {
- ERR("bulk_write short write: %s\n", usb_strerror());
- return -EFAULT;
- }
- ret = usb_bulk_read(mydev->handle, MY_EP_IN, buf, sizeof(buf), TIMEOUT);
- if(ret < 0) {
- ERR("bulk_read failed: %s\n", usb_strerror());
+ ret = recv_usb("eeprom_set[R]", mydev, MY_EP_IN, buf, sizeof(buf), TIMEOUT);
+ if(ret <= 0)
return ret;
- } else if(ret == 0)
- return 0;
phead = (struct fpga_packet_header *)buf;
- if(phead->header.op == BAD_COMMAND) {
- ERR("Firmware rejected EEPROM_SET command\n");
+ if(phead->header.op == PT_BAD_COMMAND) {
+ ERR("Firmware rejected PT_EEPROM_SET command\n");
return -EINVAL;
- } else if(phead->header.op != EEPROM_SET) {
+ } else if(phead->header.op != PT_EEPROM_SET) {
ERR("Got unexpected reply op=%d\n", phead->header.op);
return -EINVAL;
}
- if(verbose >= LOG_DEBUG) {
- DBG("%s read %d bytes\n", __FUNCTION__, ret);
- dump_packet(buf, ret);
- }
return 0;
}
#endif
@@ -292,38 +312,22 @@ int eeprom_get(struct my_usb_device *mydev)
assert(mydev != NULL);
eeprom = &mydev->eeprom;
DBG("%s Start...\n", __FUNCTION__);
- phead->header.op = EEPROM_GET;
+ phead->header.op = PT_EEPROM_GET;
len = sizeof(phead->header.op); /* warning: sending small packet */
- if(verbose >= LOG_DEBUG) {
- DBG("%s write %d bytes\n", __FUNCTION__, len);
- dump_packet(buf, len);
- }
- ret = usb_bulk_write(mydev->handle, MY_EP_OUT, (char *)phead, len, TIMEOUT);
- if(ret < 0) {
- ERR("bulk_write failed: %s\n", usb_strerror());
+ ret = send_usb("eeprom_get[W]", mydev, MY_EP_OUT, phead, len, TIMEOUT);
+ if(ret < 0)
return ret;
- } else if(ret != len) {
- ERR("bulk_write short write: %s\n", usb_strerror());
- return -EFAULT;
- }
- ret = usb_bulk_read(mydev->handle, MY_EP_IN, buf, sizeof(buf), TIMEOUT);
- if(ret < 0) {
- ERR("bulk_read failed: %s\n", usb_strerror());
+ ret = recv_usb("eeprom_get[R]", mydev, MY_EP_IN, buf, sizeof(buf), TIMEOUT);
+ if(ret <= 0)
return ret;
- } else if(ret == 0)
- return 0;
phead = (struct fpga_packet_header *)buf;
- if(phead->header.op == BAD_COMMAND) {
- ERR("BAD_COMMAND\n");
+ if(phead->header.op == PT_BAD_COMMAND) {
+ ERR("PT_BAD_COMMAND\n");
return -EINVAL;
- } else if(phead->header.op != EEPROM_GET) {
+ } else if(phead->header.op != PT_EEPROM_GET) {
ERR("Got unexpected reply op=%d\n", phead->header.op);
return -EINVAL;
}
- if(verbose >= LOG_DEBUG) {
- DBG("%s read %d bytes\n", __FUNCTION__, ret);
- dump_packet(buf, ret);
- }
memcpy(eeprom, &phead->d.eeprom_get.data, EEPROM_SIZE);
return 0;
}
@@ -345,32 +349,23 @@ int send_hexline(struct my_usb_device *mydev, struct hexline *hexline, int seq)
ERR("Bad record %d type = %d\n", seq, hexline->d.content.header.tt);
return -EINVAL;
}
- phead->header.op = DATA_PACKET;
+ phead->header.op = PT_DATA_PACKET;
phead->d.data_packet.seq = seq;
phead->d.data_packet.reserved = 0x00;
memcpy(phead->d.data_packet.data, data, len);
len += sizeof(hexline->d.content.header);
DBG("%04d+\r", seq);
- ret = usb_bulk_write(mydev->handle, MY_EP_OUT, (char *)phead, len, TIMEOUT);
- if(ret < 0) {
- ERR("bulk_write failed: %s\n", usb_strerror());
+ ret = send_usb("hexline[W]", mydev, MY_EP_OUT, phead, len, TIMEOUT);
+ if(ret < 0)
return ret;
- } else if(ret != len) {
- ERR("bulk_write short write: %s\n", usb_strerror());
- return -EFAULT;
- }
- if (verbose >= LOG_DEBUG)
- dump_packet((char*)phead, len);
- ret = usb_bulk_read(mydev->handle, MY_EP_IN, buf, sizeof(buf), TIMEOUT);
- if(ret < 0) {
- ERR("bulk_read failed: %s\n", usb_strerror());
+ ret = recv_usb("hexline[R]", mydev, MY_EP_IN, buf, sizeof(buf), TIMEOUT);
+ if(ret <= 0)
return ret;
- } else if(ret == 0)
- return 0;
DBG("%04d-\r", seq);
phead = (struct fpga_packet_header *)buf;
- if(phead->header.op != STATUS_REPLY) {
+ if(phead->header.op != PT_STATUS_REPLY) {
ERR("Got unexpected reply op=%d\n", phead->header.op);
+ dump_packet("hexline[ERR]", buf, ret);
return -EINVAL;
}
status = (enum fpga_load_status)phead->d.status_reply.status;
@@ -381,11 +376,11 @@ int send_hexline(struct my_usb_device *mydev, struct hexline *hexline, int seq)
case FW_FAIL_RESET:
case FW_FAIL_TRANS:
ERR("status reply %s (%d)\n", load_status2str(status), status);
- dump_packet(buf, ret);
+ dump_packet("hexline[ERR]", buf, ret);
return -EPROTO;
default:
ERR("Unknown status reply %d\n", status);
- dump_packet(buf, ret);
+ dump_packet("hexline[ERR]", buf, ret);
return -EPROTO;
}
return 0;
@@ -459,10 +454,6 @@ int my_usb_device_init(const char devpath[], struct my_usb_device *mydev)
ERR("Failed to open usb device '%s/%s': %s\n", mydev->dev->bus->dirname, mydev->dev->filename, usb_strerror());
return 0;
}
- if(usb_reset(mydev->handle) != 0) {
- ERR("Reseting device: usb: %s\n", usb_strerror());
- return 0;
- }
if(usb_set_configuration(mydev->handle, MY_CONFIG) != 0) {
ERR("usb: %s\n", usb_strerror());
return 0;
@@ -471,9 +462,13 @@ int my_usb_device_init(const char devpath[], struct my_usb_device *mydev)
ERR("usb: %s\n", usb_strerror());
return 0;
}
+ if(usb_reset(mydev->handle) != 0) {
+ ERR("Reseting device: usb: %s\n", usb_strerror());
+ return 0;
+ }
dev_desc = &mydev->dev->descriptor;
config_desc = mydev->dev->config;
- interface = config_desc->interface;
+ interface = &config_desc->interface[MY_INTERFACE];
iface_desc = interface->altsetting;
INFO("Vendor:Product=%04X:%04X Class=%d (endpoints=%d)\n",
dev_desc->idVendor,
@@ -520,23 +515,18 @@ int my_usb_device_init(const char devpath[], struct my_usb_device *mydev)
return 1;
}
-int renumerate_device(struct my_usb_device *mydev)
+int renumerate_device(struct my_usb_device *mydev, enum fpga_load_packet_types pt)
{
char buf[PACKET_SIZE];
struct fpga_packet_header *phead = (struct fpga_packet_header *)buf;
int ret;
assert(mydev != NULL);
- DBG("Renumerating\n");
- phead->header.op = RENUMERATE;
- ret = usb_bulk_write(mydev->handle, MY_EP_OUT, (char *)phead, 1, TIMEOUT);
- if(ret < 0) {
- ERR("bulk_write failed: %s\n", usb_strerror());
+ DBG("Renumerating with 0x%X\n", pt);
+ phead->header.op = pt;
+ ret = send_usb("renumerate[W]", mydev, MY_EP_OUT, phead, 1, TIMEOUT);
+ if(ret < 0)
return ret;
- } else if(ret != 1) {
- ERR("bulk_write short write: %s\n", usb_strerror());
- return -EFAULT;
- }
return 0;
}
@@ -597,8 +587,10 @@ void usage()
{
fprintf(stderr, "Usage: %s -D {/proc/bus/usb|/dev/bus/usb}/<bus>/<dev> [options...]\n", progname);
fprintf(stderr, "\tOptions:\n");
- fprintf(stderr, "\t\t[-b <binfile>] # output to <binfile>\n");
+ fprintf(stderr, "\t\t[-r] # Reset the device\n");
+ fprintf(stderr, "\t\t[-b <binfile>] # Output to <binfile>\n");
fprintf(stderr, "\t\t[-I <hexfile>] # Input from <hexfile>\n");
+ fprintf(stderr, "\t\t[-i] # Show hexfile information\n");
fprintf(stderr, "\t\t[-g] # Get eeprom from device\n");
#ifdef XORCOM_INTERNAL
fprintf(stderr, "\t\t[-C srC byte] # Set Address sourCe (default: C0)\n");
@@ -627,6 +619,8 @@ int main(int argc, char *argv[])
const char *binfile = NULL;
const char *hexfile = NULL;
struct hexdata *hexdata = NULL;
+ int opt_reset = 0;
+ int opt_info = 0;
int opt_read_eeprom = 0;
#ifdef XORCOM_INTERNAL
int opt_write_eeprom = 0;
@@ -637,9 +631,9 @@ int main(int argc, char *argv[])
char *release = NULL;
char *serial = NULL;
uint8_t serial_buf[SERIAL_SIZE];
- const char options[] = "b:C:D:ghI:vV:P:R:S:";
+ const char options[] = "rib:C:D:ghI:vV:P:R:S:";
#else
- const char options[] = "b:D:ghI:v";
+ const char options[] = "rib:D:ghI:v";
#endif
int ret = 0;
@@ -657,6 +651,12 @@ int main(int argc, char *argv[])
case 'D':
devpath = optarg;
break;
+ case 'r':
+ opt_reset = 1;
+ break;
+ case 'i':
+ opt_info = 1;
+ break;
case 'b':
binfile = optarg;
break;
@@ -725,10 +725,15 @@ int main(int argc, char *argv[])
ERR("Bailing out\n");
exit(1);
}
- if(binfile) {
+ if(opt_info) {
+ printf("%s: Version=%s Checksum=%d\n",
+ hexfile, hexdata->version_info,
+ calc_checksum(hexdata));
+ }
+ if(binfile)
dump_binary(hexdata, binfile);
+ if(!devpath)
return 0;
- }
}
if(!devpath) {
ERR("Missing device path\n");
@@ -761,7 +766,7 @@ int main(int argc, char *argv[])
ret = -ENODEV;
goto dev_err;
}
- ret = renumerate_device(&mydev);
+ ret = renumerate_device(&mydev, PT_RENUMERATE);
if(ret < 0) {
ERR("Renumeration failed: errno=%d\n", ret);
goto dev_err;
@@ -798,6 +803,14 @@ int main(int argc, char *argv[])
show_device_info(&mydev);
}
#endif
+ if(opt_reset) {
+ DBG("Reseting to default\n");
+ ret = renumerate_device(&mydev, PT_RESET);
+ if(ret < 0) {
+ ERR("Renumeration to default failed: errno=%d\n", ret);
+ goto dev_err;
+ }
+ }
DBG("Exiting\n");
dev_err:
my_usb_device_cleanup(&mydev);
diff --git a/xpp/utils/genzaptelconf b/xpp/utils/genzaptelconf
index 67a0263..4bf8a38 100755
--- a/xpp/utils/genzaptelconf
+++ b/xpp/utils/genzaptelconf
@@ -66,12 +66,18 @@ MODLIST_FILE=/etc/modules
MODLIST_FILE_FEDORA=/etc/sysconfig/zaptel
exten_base_dir=/etc/asterisk/extensions-phones.d
exten_defs_file=/etc/asterisk/extensions-defs.conf
+# perl utilities:
+xpp_sync=/usr/sbin/xpp_sync
+zt_registration=/usr/sbin/zt_registration
# how long to wait for /dev/zap/ctl to appear? (seconds)
DEVZAP_TIMEOUT=${DEVZAP_TIMEOUT:-20}
ZTCFG=${ZTCFG:-/sbin/ztcfg}
# BRI/PRI spans will be in an additional per-span group whose number
# is SPAN_GROUP_BASE + span-number
SPAN_GROUP_BASE=10
+# set to "yes" to make BRI NT spans set overlapdial (handy for ISDN phones
+# and other devices).
+brint_overlap=no
# a temporary directory to store whatever we need to remember.
#
@@ -83,6 +89,12 @@ tmp_dir=
# - The module that will be deleted from /etc/modules , if -d -M is used
ALL_MODULES="vzaphfc zaphfc qozap ztgsm wctdm wctdm24xxp wcfxo wcfxs pciradio tor2 torisa wcte12xp wct1xxp wct4xxp wcte11xp wanpipe wcusb xpp_usb"
+# The name of the variable in /etc/sysconfig/zaptel into which to set
+# the list of detected modules.
+modules_var=MODULES
+# On SuSE with the rpm package:
+#modules_var=ZAPTEL_MODULES
+
# What signalling to give to ZapBRI channels?
# bri: bri_net; bri_cpe (Bristuffed Asterisk. No multi- support)
# bri_ptmpi: bri_net_ptmp; bri_cpe_ptmp (Bristuffed Asterisk, multi- support)
@@ -106,6 +118,8 @@ if [ ! -x "$ZTCFG" ]; then
fi
fi
+XPP_SYNC=auto # sync mode. can be set to '0' or '1' or HOST explicitly.
+
# it is safe to use -c twice: the last one will be used.
ztcfg_cmd="$ZTCFG -c $ZAPCONF_FILE"
@@ -197,8 +211,8 @@ update_module_list_debian() {
update_module_list_fedora() {
say "Updating modules list in zaptel init config $MODLIST_FILE_FEDORA."
- sed -i.bak -e '/^MODULES=/d' "$MODLIST_FILE_FEDORA"
- echo "MODULES=\"$*\"" >> "$MODLIST_FILE_FEDORA"
+ sed -i.bak -e "/^$modules_var=/d" "$MODLIST_FILE_FEDORA"
+ echo "$modules_var=\"$*\"" >> "$MODLIST_FILE_FEDORA"
}
update_module_list() {
@@ -234,6 +248,26 @@ zap_reg_xpp() {
done
}
+# Initialize the Xorcom Astribank (xpp/)
+xpp_startup() {
+ # do nothing if the module xpp was not loaded, or if no
+ # Astribanks connected:
+ if [ ! -d /proc/xpp ]; then return 0; fi
+ if ! grep -q 'STATUS=connected' /proc/xpp/xbuses; then return 0; fi
+
+ echo "Waiting for Astribank devices to initialize:"
+ cat /proc/xpp/XBUS-[0-9]*/waitfor_xpds 2>/dev/null || true
+
+ # overriding locales for the above two, as perl can be noisy
+ # when locales are missing.
+ # No register all the devices if they didn't auto-register:
+ LC_ALL=C $zt_registration on
+
+ # this one could actually be run after ztcfg:
+ LC_ALL=C $xpp_sync "$XPP_SYNC"
+}
+
+
usage() {
program=`basename $0`
@@ -306,8 +340,8 @@ print_pattern() {
method="$fxs_default_start"
fi
case "$sig" in
- fxs) sig_name=FXO; sig_name_sc=fxo ;;
- fxo) sig_name=FXS; sig_name_sc=fxs ;;
+ fxs) sig_name=FXO;;
+ fxo) sig_name=FXS;;
esac
case "$mode" in
list)
@@ -419,7 +453,7 @@ print_pattern() {
reset_zapata_entry $zapata_file $reset_values
echo "" >> $zapata_file
- print_zapscan_port "$sig_name_sc" "$chan"
+ print_zapscan_port "$sig" "$chan"
;;
esac
@@ -547,7 +581,7 @@ temporary_zapconf() {
case "$1" in
save)
say "Temporarily moving zaptel.conf aside to work around broken modprobe.conf"
- ZAPCONF_FILE_TMP=`mktemp -t zaptel.conf-XXXXXX` || die "Error creating temporary zaptel.conf"
+ ZAPCONF_FILE_TMP=`mktemp /tmp/genzaptelconf-zaptel.conf-XXXXXX` || die "Error creating temporary zaptel.conf"
cp -a $ZAPCONF_FILE_SYSTEM $ZAPCONF_FILE_TMP
echo -n >$ZAPCONF_FILE_SYSTEM
;;
@@ -566,12 +600,13 @@ reset_zapata_entry() {
for arg in "$@"; do
case "$arg" in
- busydetect) echo "busydetect=no" >>$conf_file;;
- context) echo "context=default" >>$conf_file;;
- immediate) echo "immediate=no" >>$conf_file;;
- rxgain) echo "rxgain=0" >>$conf_file;;
- txgain) echo "txgain=0" >>$conf_file;;
- *) echo "$arg=" >>$conf_file;;
+ busydetect) echo "$arg=no" >>$conf_file;;
+ context) echo "$arg=default" >>$conf_file;;
+ immediate) echo "$arg=no" >>$conf_file;;
+ overlapdial) echo "$arg=no" >>$conf_file;;
+ rxgain) echo "$arg=0" >>$conf_file;;
+ txgain) echo "$arg=0" >>$conf_file;;
+ *) echo "$arg=" >>$conf_file;;
esac
done
}
@@ -594,7 +629,9 @@ gen_tmp_conf() {
orig_cfg_file=$1
new_var=$2
- eval $new_var=`mktemp -t genzaptelconf-zapata-XXXXXX` # assign by reference
+ # assign to new_var by reference:
+ eval $new_var=`mktemp /tmp/genzaptelconf-conf-XXXXXX` \
+ || die "Unable to create temporary config file for $orig_cfg_file"
if [ -r "$orig_cfg_file" ]; then
chown --reference="$orig_cfg_file" ${!new_var} 2>/dev/null
chmod --reference="$orig_cfg_file" ${!new_var} 2>/dev/null
@@ -731,8 +768,12 @@ write_digital_config() {
if [ "$span_termtype" != '' ]
then echo "# termtype: $span_termtype" >>$zaptel_file
fi
+
echo bchan=$bchans >>$zaptel_file
echo dchan=$dchan >>$zaptel_file
+ if [ "$fxsdisable" = 'yes' ] && [ "$span_termtype" = 'nt' ]; then return; fi
+ # You should not send content to zapata.conf below this line
+
span_group=$(($SPAN_GROUP_BASE + $span_num))
if [ "$span_termtype" != '' ]
@@ -744,6 +785,11 @@ write_digital_config() {
echo "callerid=\"Channels $span_begin - $span_end\" <$span_begin>" >> $zapata_file
reset_values="$reset_values callerid"
#echo "mailbox=$exten"
+ if [ "$brint_overlap" = 'yes' ]
+ then
+ echo "overlapdial=yes" >> $zapata_file
+ reset_values="$reset_values overlapdial"
+ fi
if [ "$group_manual" != "yes" ]
then
echo "group=$group_phones,$span_group" >> $zapata_file
@@ -970,6 +1016,14 @@ EOF
mv $ZAPSCAN_FILE $ZAPSCAN_FILE.bak 2>/dev/null
mv $zapscan_file $ZAPSCAN_FILE
fi
+
+ zapata_file_name=`basename $ZAPATA_FILE`
+ if ! grep -q "^#include.*$zapata_file_name" \
+ /etc/asterisk/zapata.conf
+ then
+ say "Note: generated $ZAPATA_FILE not included in zapata.conf"
+ say "To fix: echo '#include $zapata_file_name' >>/etc/asterisk/zapata.conf"
+ fi
fi
}
@@ -1001,7 +1055,7 @@ if [ $# != 0 ]; then
exit 1
fi
-tmp_dir=`mktemp -d -t` || \
+tmp_dir=`mktemp -d /tmp/genzaptelconf-dir-XXXXXX` || \
die "$0: failed to create temporary directory. Aborting"
@@ -1050,7 +1104,8 @@ fi
if [ "$mode" = list ]; then
genconf list
else
- zap_reg_xpp
+ #zap_reg_xpp
+ xpp_startup
wait_for_zapctl
say "Generating '${ZAPCONF_FILE} and ${ZAPATA_FILE}'"
genconf files
diff --git a/xpp/utils/hexfile.c b/xpp/utils/hexfile.c
index a4b12c5..5d6eaa7 100644
--- a/xpp/utils/hexfile.c
+++ b/xpp/utils/hexfile.c
@@ -278,6 +278,39 @@ int dump_hexfile2(struct hexdata *hexdata, FILE *outfile, uint8_t maxwidth)
return 0;
}
+void process_comment(struct hexdata *hexdata, char buf[])
+{
+ char *dollar_start;
+ char *dollar_end;
+ const char id_prefix[] = "Id: ";
+ char tmp[BUFSIZ];
+ char *p;
+ int len;
+
+ if(report_func)
+ report_func(LOG_INFO, "Comment: %s\n", buf + 1);
+ /* Search for RCS keywords */
+ if((dollar_start = strchr(buf, '$')) == NULL)
+ return;
+ if((dollar_end = strchr(dollar_start + 1, '$')) == NULL)
+ return;
+ /* Crop the '$' signs */
+ len = dollar_end - dollar_start;
+ len -= 2;
+ memcpy(tmp, dollar_start + 1, len);
+ tmp[len] = '\0';
+ p = tmp;
+ if(strstr(tmp, id_prefix) == NULL)
+ return;
+ p += strlen(id_prefix);
+ if((p = strchr(p, ' ')) == NULL)
+ return;
+ p++;
+ strncpy(hexdata->version_info, p, BUFSIZ - 1);
+ if((p = strchr(hexdata->version_info, ' ')) != NULL)
+ *p = '\0';
+}
+
struct hexdata *parse_hexfile(const char *fname, unsigned int maxlines)
{
FILE *fp;
@@ -314,18 +347,7 @@ struct hexdata *parse_hexfile(const char *fname, unsigned int maxlines)
}
chomp(buf);
if(buf[0] == '#') {
- char *dollar_start;
- char *dollar_end;
-
- if(report_func)
- report_func(LOG_INFO, "Comment: %s\n", buf + 1);
- /* Search for RCS keywords */
- if((dollar_start = strchr(buf, '$')) == NULL)
- continue;
- if((dollar_end = strchr(dollar_start + 1, '$')) == NULL)
- continue;
- *(dollar_end + 1) = '\0';
- strncpy(hexdata->version_info, dollar_start, BUFSIZ - 1);
+ process_comment(hexdata, buf);
continue;
}
if(buf[0] != ':') {
@@ -383,3 +405,31 @@ void dump_binary(struct hexdata *hexdata, const char *outfile)
fclose(fp);
}
+/*
+ * Algorithm lifted of sum(1) implementation from coreutils.
+ * We chose the default algorithm (BSD style).
+ */
+int calc_checksum(struct hexdata *hexdata)
+{
+ unsigned int i;
+ size_t len;
+ int ck = 0;
+
+ for(i = 0; i < hexdata->maxlines; i++) {
+ struct hexline *hexline = hexdata->lines[i];
+ unsigned char *p;
+
+ if(!hexline)
+ break;
+ if(hexline->d.content.header.tt == TT_EOF)
+ continue;
+ len = hexline->d.content.header.ll;
+ p = hexline->d.content.tt_data.data;
+ for(; len; p++, len--) {
+ ck = (ck >> 1) + ((ck & 1) << 15);
+ ck += *p;
+ ck &= 0xffff; /* Keep it within bounds. */
+ }
+ }
+ return ck;
+}
diff --git a/xpp/utils/hexfile.h b/xpp/utils/hexfile.h
index 4c6e689..297cfba 100644
--- a/xpp/utils/hexfile.h
+++ b/xpp/utils/hexfile.h
@@ -116,6 +116,7 @@ struct hexdata *parse_hexfile(const char *fname, unsigned int maxlines);
int dump_hexfile(struct hexdata *hexdata, FILE *outfile);
int dump_hexfile2(struct hexdata *hexdata, FILE *outfile, uint8_t maxwidth);
void dump_binary(struct hexdata *hexdata, const char *outfile);
+int calc_checksum(struct hexdata *hexdata);
__END_DECLS
#endif
diff --git a/xpp/utils/lszaptel b/xpp/utils/lszaptel
index af11b6e..4a6f8b9 100755
--- a/xpp/utils/lszaptel
+++ b/xpp/utils/lszaptel
@@ -5,7 +5,9 @@
# This program is free software; you can redistribute and/or
# modify it under the same terms as Perl itself.
#
-#use strict;
+# $Id$
+#
+use strict;
BEGIN { my $dir = $0; $dir =~ s:/[^/]+$::; unshift(@INC, "$dir", "$dir/zconf"); }
use Zaptel;
diff --git a/xpp/utils/xpp_blink b/xpp/utils/xpp_blink
new file mode 100755
index 0000000..1993a81
--- /dev/null
+++ b/xpp/utils/xpp_blink
@@ -0,0 +1,115 @@
+#! /usr/bin/perl -w
+#
+# Written by Oron Peled <oron@actcom.co.il>
+# Copyright (C) 2007, Xorcom
+# This program is free software; you can redistribute and/or
+# modify it under the same terms as Perl itself.
+#
+# $Id$
+#
+use strict;
+BEGIN { my $dir = $0; $dir =~ s:/[^/]+$::; unshift(@INC, "$dir", "$dir/zconf"); }
+
+use Zaptel;
+use Zaptel::Span;
+use Zaptel::Xpp;
+use Zaptel::Xpp::Xbus;
+
+sub usage {
+ die "Usage: $0 {on|off|bzzt} {span <number> | xpd <bus num> [<xpd num>]}\n";
+}
+
+my $state = shift;
+my $selector = shift;
+usage unless defined($state) and $state =~ /^(on|off|bzzt)$/;
+usage unless defined($selector) and $selector =~ /^(span|xpd)$/i;
+
+my $xpd;
+my @xpds;
+my @channels;
+
+if($selector =~ /^span$/i) {
+ my $number = shift;
+ usage unless defined($number) and $number =~ /^\d+/;
+ my $span = Zaptel::Span::by_number($number);
+ die "Unkown Span $number\n" unless $span;
+ $xpd = Zaptel::Xpp::xpd_of_span($span);
+ die "Span $number is not an XPD\n" unless defined $xpd;
+ my $xpdname = $xpd->fqn;
+ my $connector = $xpd->xbus->connector;
+ die "$xpdname is not connected\n" unless defined $connector;
+ push(@xpds, $xpd);
+ my @chans = $span->chans();
+ @channels = join(' ', map { $_->num } @chans);
+ printf "Using %s (connected via $connector): channels @channels\n", $xpd->fqn;
+} elsif($selector =~ /^xpd$/i) {
+ my $busnum = shift;
+ my $xpdnum = shift;
+ usage unless defined($busnum) and $busnum =~ /^\d+/;
+ my $xbus = Zaptel::Xpp::Xbus::by_number($busnum);
+ die "Unkown XBUS number $busnum\n" unless defined $xbus;
+ if(defined $xpdnum) {
+ usage unless $xpdnum =~ /^\d+/;
+ $xpd = $xbus->get_xpd_by_number($xpdnum);
+ die "Unkown XPD number $xpdnum on XBUS number $busnum\n" unless defined $xpd;
+ push(@xpds, $xpd);
+ } else {
+ @xpds = $xbus->xpds;
+ die "XBUS number $busnum has no XPDS!\n" unless @xpds;
+ }
+}
+
+if($state eq 'on') {
+ $_->blink(1) foreach (@xpds);
+} elsif($state eq 'off') {
+ $_->blink(0) foreach (@xpds);
+} elsif($state eq 'bzzt') {
+ $_->blink(1) foreach (@xpds);
+ sleep 1;
+ $_->blink(0) foreach (@xpds);
+}
+
+__END__
+
+=head1 NAME
+
+xpp_blink - Blink the leds of a specified XPD
+
+=head1 SYNOPSIS
+
+xpp_blink {on|off|bzzt} {span <number> | xpd <bus num> [<xpd num>]}\n";
+
+=head1 DESCRIPTION
+
+Blink all the leds of an XPD.
+
+=head2 Blink mode:
+
+=over 16
+
+=item on Turn on constant blink
+
+=item off Turn off blink
+
+=item bzzt Blink briefly for 1 second.
+
+=back
+
+=head2 Selector:
+
+=over 16
+
+=item span Select by span number. This only work for XPD registered to zaptel.
+
+=item xpd Select by xbus + xpd numbers. If only xbus number is given, all the
+ XPDs of the selected xbus are blinked.
+
+=back
+
+=head1 EXAMPLES
+
+ $ xpp_blink bzzt span 2
+
+ $ xpp_blink xpd 0 1
+
+ $ xpp_blink xpd 0
diff --git a/xpp/utils/xpp_fxloader b/xpp/utils/xpp_fxloader
index 3d200e8..eb46ccc 100644
--- a/xpp/utils/xpp_fxloader
+++ b/xpp/utils/xpp_fxloader
@@ -48,6 +48,10 @@
set -e
+# Make sure fxload is in the path:
+PATH="$PATH:/usr/local/sbin:/sbin:/usr/sbin"
+export PATH
+
me=`basename $0`
DEFAULTS="/etc/default/zaptel"
@@ -119,10 +123,22 @@ load_fw() {
if [ "$devices" != '' ]; then sleep $REENUM_SLEEP_TIME; fi
}
-hexfile_version() {
- hexfile=$1
+reset_fpga() {
+ v_id=$1
+ p_id=$2
- grep '$Id:' "$hexfile" | sed -e 's/^.*$Id: *[^ ]\+ *//' -e 's/ .*$//'
+ devices=`find_dev $v_id $p_id`
+ for dev in $devices
+ do
+ $LOGGER "Resetting FPGA Firmware on $dev"
+ sleep_if_race
+ $FPGA_LOAD -D "$dev" -r 2>&1 >/dev/null | $LOGGER
+ status=$PIPESTATUS
+ if [ "$status" != 0 ]; then
+ echo "fpga_load failed remoivng with status $status" | $LOGGER
+ exit 78
+ fi
+ done
}
load_fpga() {
@@ -134,11 +150,10 @@ load_fpga() {
for dev in $devices
do
card_ver=`$FPGA_LOAD -g -D $dev | sed -n 's/^.*Release: *//'`
- firm_ver=`hexfile_version $FIRMWARE_DIR/$fw`
- $LOGGER "FPGA Firmware $FIRMWARE_DIR/$fw (version: $firm_ver) into $dev"
+ $LOGGER "FPGA Firmware into $dev"
sleep_if_race
- $FPGA_LOAD -D "$dev" -I "$FIRMWARE_DIR/$fw" 2>&1 >/dev/null | $LOGGER
+ $FPGA_LOAD -D "$dev" -I "$FIRMWARE_DIR/$fw" -i | $LOGGER
status=$PIPESTATUS
if [ $status != 0 ]; then
echo "fpga_load failed with status $status" | $LOGGER
@@ -160,6 +175,10 @@ udev)
PRODUCT="$2"
# skip on to the rest of the script. Don't exit.
;;
+reset)
+ # TODO: does the use of wildcards here work?
+ reset_fpga e4e4 '11[345][12]'
+ ;;
xppdetect|load|usb)
echo "--------- FIRMWARE LOADING: ($1)"
@@ -195,6 +214,9 @@ esac
## Hotplug run
##
+# allow disabling automatic hotplugging:
+if [ "$XPP_HOTPLUG_DISABLED" != '' ]; then return 0; fi
+
if [ "$ACTION" = "add" ] && [ -w "$DEVICE" ]
then
$LOGGER "Trying to find what to do for product $PRODUCT, device $DEVICE"
diff --git a/xpp/utils/xpp_sync b/xpp/utils/xpp_sync
index 018d268..e1258d9 100755
--- a/xpp/utils/xpp_sync
+++ b/xpp/utils/xpp_sync
@@ -5,7 +5,9 @@
# This program is free software; you can redistribute and/or
# modify it under the same terms as Perl itself.
#
-#use strict;
+# $Id$
+#
+use strict;
BEGIN { my $dir = $0; $dir =~ s:/[^/]+$::; unshift(@INC, "$dir", "$dir/zconf"); }
use Zaptel::Xpp;
@@ -19,6 +21,7 @@ if(@ARGV == 1) {
$autoselect = 1 if $sync =~ /^auto$/i;
}
+
sub get_sorted_xpds() {
my @good_xpds;
@@ -31,7 +34,7 @@ sub get_sorted_xpds() {
next;
}
next unless $isreg; # Skip unregistered XPDs
- push(@good_xpds, $xpd);
+ push(@good_xpds, $xpd);
}
}
@@ -70,21 +73,45 @@ sub do_set($) {
die "Failed to set sync to '$sync'" unless Zaptel::Xpp::sync($sync);
}
+sub unique_xbus(@) {
+ my %seen;
+
+ grep { !$seen{$_->xbus}++; } @_;
+}
+
my $curr_sync = Zaptel::Xpp::sync;
-my %xbus_seen;
-my @sorted_xpds = grep { !$xbus_seen{$_->xbus}++; } get_sorted_xpds;
+my @sync_xpds = unique_xbus(get_sorted_xpds());
+
+sub check_fxo_host_sync() {
+ my @host_synced_xpds = grep { $_->xbus->num() ne $curr_sync } @sync_xpds;
+ my @host_synced_fxos = grep($_->type eq 'FXO', @host_synced_xpds);
+ if(@host_synced_fxos) {
+ my @bad_xbus = map { $_->xbus } unique_xbus(@host_synced_fxos);
+ our $lines = join("\n\t", map { $_->name } @bad_xbus);
+ print STDERR <<"END";
+=========================================
+WARNING: FXO with HOST SYNC cause bad PCM
+ Affected Astribanks are:
+-----------------------------------------
+ $lines
+=========================================
+END
+ }
+}
+
if($sync) {
if($autoselect) {
- do_select(@sorted_xpds);
+ do_select(@sync_xpds);
} else {
$sync = uc($sync);
do_set($sync);
}
+ $curr_sync = Zaptel::Xpp::sync;
#print "New sync: ", Zaptel::Xpp::sync, "\n";
} else {
print "Current sync: ", $curr_sync, "\n";
print "Best Available Syncers:\n";
- foreach my $xpd (@sorted_xpds) {
+ foreach my $xpd (@sync_xpds) {
my $xbus = $xpd->xbus;
my @xpds = $xbus->xpds;
my @types = map { $_->type } @xpds;
@@ -101,12 +128,13 @@ if($sync) {
$next = $n + 1;
}
# Fill spaces to end
- $n = 4;
+ my $n = 4;
for(my $i = $next; $i < $n; $i++) {
printf "%-3s ", "";
}
printf "] (%s)\n", $xbus->connector;
}
+ check_fxo_host_sync;
}
__END__
diff --git a/xpp/utils/zconf/Zaptel.pm b/xpp/utils/zconf/Zaptel.pm
index 394aa8e..7642b0e 100644
--- a/xpp/utils/zconf/Zaptel.pm
+++ b/xpp/utils/zconf/Zaptel.pm
@@ -5,7 +5,10 @@ package Zaptel;
# This program is free software; you can redistribute and/or
# modify it under the same terms as Perl itself.
#
-#use strict;
+# $Id$
+#
+use strict;
+use Zaptel::Span;
my $proc_base = "/proc/zaptel";
diff --git a/xpp/utils/zconf/Zaptel/Chans.pm b/xpp/utils/zconf/Zaptel/Chans.pm
index 31bc5f7..3364060 100644
--- a/xpp/utils/zconf/Zaptel/Chans.pm
+++ b/xpp/utils/zconf/Zaptel/Chans.pm
@@ -5,9 +5,12 @@ package Zaptel::Chans;
# This program is free software; you can redistribute and/or
# modify it under the same terms as Perl itself.
#
-#use strict;
+# $Id$
+#
+use strict;
# Accessors (miniperl does not have Class:Accessor)
+our $AUTOLOAD;
sub AUTOLOAD {
my $self = shift;
my $name = uc($AUTOLOAD);
@@ -36,11 +39,42 @@ sub new($$$$$) {
$type = $1; # One of our AB
} elsif(defined $info) {
$type = (split(/\s+/, $info))[0];
+ $type = 'FXS' if $type =~ /^FXS/;
+ $type = 'FXO' if $type =~ /^FXO/;
} else {
- $type = $fqn;
+ $type = undef;
}
$self->type($type);
return $self;
}
+my $ztcfg = $ENV{ZTCFG} || '/sbin/ztcfg';
+sub probe_type($) {
+ my $self = shift;
+ my $fqn = $self->fqn;
+ my $num = $self->num;
+ my $type;
+
+ if($fqn =~ m:WCTDM/|\ WRTDM/|OPVXA1200/:) {
+ my %maybe;
+
+ undef %maybe;
+ foreach my $sig (qw(fxo fxs)) {
+ my $cmd = "echo ${sig}ks=$num | $ztcfg -c /dev/fd/0";
+
+ $maybe{$sig} = system("$cmd >/dev/null 2>&1") == 0;
+ }
+ if($maybe{fxo} and $maybe{fxs}) {
+ $type = 'EMPTY';
+ } elsif($maybe{fxo}) {
+ $type = 'FXS';
+ } elsif($maybe{fxs}) {
+ $type = 'FXO';
+ }
+ } else {
+ $type = $self->type;
+ }
+ return $type;
+}
+
1;
diff --git a/xpp/utils/zconf/Zaptel/Span.pm b/xpp/utils/zconf/Zaptel/Span.pm
index 08ebae2..c020d2f 100644
--- a/xpp/utils/zconf/Zaptel/Span.pm
+++ b/xpp/utils/zconf/Zaptel/Span.pm
@@ -5,7 +5,9 @@ package Zaptel::Span;
# This program is free software; you can redistribute and/or
# modify it under the same terms as Perl itself.
#
-#use strict;
+# $Id$
+#
+use strict;
use Zaptel::Chans;
my $proc_base = "/proc/zaptel";
@@ -16,6 +18,7 @@ sub chans($) {
}
# Accessors (miniperl does not have Class:Accessor)
+our $AUTOLOAD;
sub AUTOLOAD {
my $self = shift;
my $name = uc($AUTOLOAD);
@@ -27,6 +30,25 @@ sub AUTOLOAD {
}
}
+sub by_number($) {
+ my $span_number = shift;
+ die "Missing span number" unless defined $span_number;
+ my @spans = Zaptel::spans();
+
+ my ($span) = grep { $_->num == $span_number } @spans;
+ return $span;
+}
+
+my @bri_strings = (
+ 'BRI_(NT|TE)',
+ '(?:quad|octo)BRI PCI ISDN Card.* \[(NT|TE)\]\ ',
+ 'octoBRI \[(NT|TE)\] ',
+ 'HFC-S PCI A ISDN.* \[(NT|TE)\] '
+ );
+
+our $ZAPBRI_NET = 'bri_net';
+our $ZAPBRI_CPE = 'bri_cpe';
+
sub new($$) {
my $pack = shift or die "Wasn't called as a class method\n";
my $num = shift or die "Missing a span number parameter\n";
@@ -35,6 +57,17 @@ sub new($$) {
open(F, "$proc_base/$num") or die "Failed to open '$proc_base/$num\n";
my $head = <F>;
chomp $head;
+ foreach my $cardtype (@bri_strings) {
+ if($head =~ m/$cardtype/) {
+ $self->{IS_BRI} = 1;
+ $self->{TERMTYPE} = $1;
+ $self->{DCHAN_IDX} = 2;
+ $self->{BCHAN_LIST} = [ 0, 1 ];
+ last;
+ }
+ }
+ die "$0: Unkown TERMTYPE [NT/TE]\n"
+ if $self->is_bri and !defined $self->{TERMTYPE};
($self->{NAME}, $self->{DESCRIPTION}) = (split(/\s+/, $head, 4))[2, 3];
$self->{CHANS} = [];
while(<F>) {
@@ -47,7 +80,30 @@ sub new($$) {
push(@{$self->{CHANS}}, $c);
}
close F;
+ if($self->is_bri()) {
+ $self->{CODING} = 'ami';
+ $self->{YELLOW} = undef;
+ $self->{DCHAN} = ($self->chans())[$self->{DCHAN_IDX}];
+ $self->{BCHANS} = [ ($self->chans())[@{$self->{BCHAN_LIST}}] ];
+ # Infer some info from channel name:
+ my $first_chan = ($self->chans())[0] || die "$0: No channels in span #$num\n";
+ my $chan_fqn = $first_chan->fqn();
+ if($chan_fqn =~ m(ZTHFC.*/|ztqoz.*/|XPP_BRI_.*/)) { # BRI
+ $self->{FRAMING} = 'ccs';
+ $self->{SWITCHTYPE} = 'euroisdn';
+ $self->{SIGNALLING} = ($self->{TERMTYPE} eq 'NT') ? $ZAPBRI_NET : $ZAPBRI_CPE ;
+ } elsif($chan_fqn =~ m(ztgsm.*/)) { # Junghanns's GSM cards.
+ $self->{FRAMING} = 'ccs';
+ $self->{SIGNALLING} = 'gsm';
+ }
+ }
return $self;
}
+sub bchans($) {
+ my $self = shift || die;
+
+ return @{$self->{BCHANS}};
+}
+
1;
diff --git a/xpp/utils/zconf/Zaptel/Xpp.pm b/xpp/utils/zconf/Zaptel/Xpp.pm
index b627438..dd1f34c 100644
--- a/xpp/utils/zconf/Zaptel/Xpp.pm
+++ b/xpp/utils/zconf/Zaptel/Xpp.pm
@@ -5,7 +5,9 @@ package Zaptel::Xpp;
# This program is free software; you can redistribute and/or
# modify it under the same terms as Perl itself.
#
-#use strict;
+# $Id$
+#
+use strict;
use Zaptel::Xpp::Xbus;
my $proc_base = "/proc/xpp";
@@ -33,7 +35,7 @@ sub xbuses {
$name =~ s/://;
$name =~ /XBUS-(\d\d)/ or die "Bad XBUS number: $name";
my $num = $1;
- @attr = map { $_ = uc($_); split(/=/); } @attr;
+ @attr = map { split(/=/); } @attr;
my $xbus = Zaptel::Xpp::Xbus->new(NAME => $name, NUM => $num, @attr);
push(@xbuses, $xbus);
}
@@ -51,6 +53,17 @@ sub xbuses {
return sort $sorter @xbuses;
}
+sub xpd_of_span($) {
+ my $span = shift or die "Missing span parameter";
+ return undef unless defined $span;
+ foreach my $xbus (Zaptel::Xpp::xbuses('SORT_CONNECTOR')) {
+ foreach my $xpd ($xbus->xpds()) {
+ return $xpd if $xpd->fqn eq $span->name;
+ }
+ }
+ return undef;
+}
+
sub sync {
my $newsync = shift;
my $result;
diff --git a/xpp/utils/zconf/Zaptel/Xpp/Xbus.pm b/xpp/utils/zconf/Zaptel/Xpp/Xbus.pm
index 8d9d340..772e050 100644
--- a/xpp/utils/zconf/Zaptel/Xpp/Xbus.pm
+++ b/xpp/utils/zconf/Zaptel/Xpp/Xbus.pm
@@ -5,12 +5,15 @@ package Zaptel::Xpp::Xbus;
# This program is free software; you can redistribute and/or
# modify it under the same terms as Perl itself.
#
-#use strict;
+# $Id$
+#
+use strict;
use Zaptel::Xpp::Xpd;
my $proc_base = "/proc/xpp";
# Accessors (miniperl does not have Class:Accessor)
+our $AUTOLOAD;
sub AUTOLOAD {
my $self = shift;
my $name = uc($AUTOLOAD);
@@ -27,9 +30,37 @@ sub xpds($) {
return @{$xbus->{XPDS}};
}
+sub by_number($) {
+ my $busnumber = shift;
+ die "Missing xbus number parameter" unless defined $busnumber;
+ my @xbuses = Zaptel::Xpp::xbuses();
+
+ my ($xbus) = grep { $_->num == $busnumber } @xbuses;
+ return $xbus;
+}
+
+sub get_xpd_by_number($$) {
+ my $xbus = shift;
+ my $xpdnum = shift;
+ die "Missing XPD number parameter" unless defined $xpdnum;
+ my @xpds = $xbus->xpds;
+ return $xpds[$xpdnum];
+}
+
sub new($$) {
my $pack = shift or die "Wasn't called as a class method\n";
- my $self = { @_ };
+ my $self = {};
+ while(@_) {
+ my ($k, $v) = @_;
+ shift; shift;
+ # Keys in all caps
+ $k = uc($k);
+ # Some values are in all caps as well
+ if($k =~ /^(STATUS)$/) {
+ $v = uc($v);
+ }
+ $self->{$k} = $v;
+ }
bless $self, $pack;
$self->{NAME} or die "Missing xbus name";
my $prefix = "$proc_base/" . $self->{NAME};
@@ -45,6 +76,7 @@ sub new($$) {
);
push(@{$self->{XPDS}}, $xpd);
}
+ @{$self->{XPDS}} = sort { $a->num <=> $b->num } @{$self->{XPDS}};
return $self;
}
diff --git a/xpp/utils/zconf/Zaptel/Xpp/Xpd.pm b/xpp/utils/zconf/Zaptel/Xpp/Xpd.pm
index 180b7ea..94176b8 100644
--- a/xpp/utils/zconf/Zaptel/Xpp/Xpd.pm
+++ b/xpp/utils/zconf/Zaptel/Xpp/Xpd.pm
@@ -5,11 +5,14 @@ package Zaptel::Xpp::Xpd;
# This program is free software; you can redistribute and/or
# modify it under the same terms as Perl itself.
#
-#use strict;
+# $Id$
+#
+use strict;
my $proc_base = "/proc/xpp";
# Accessors (miniperl does not have Class:Accessor)
+our $AUTOLOAD;
sub AUTOLOAD {
my $self = shift;
my $name = uc($AUTOLOAD);
@@ -21,6 +24,32 @@ sub AUTOLOAD {
}
}
+sub blink($$) {
+ my $self = shift;
+ my $on = shift;
+ my $result;
+
+ my $file = "$proc_base/" . $self->fqn . "/blink";
+ die "$file is missing" unless -f $file;
+ # First query
+ open(F, "$file") or die "Failed to open $file for reading: $!";
+ $result = <F>;
+ chomp $result;
+ close F;
+ if(defined($on) and $on ne $result) { # Now change
+ open(F, ">$file") or die "Failed to open $file for writing: $!";
+ print F ($on)?"1":"0";
+ if(!close(F)) {
+ if($! == 17) { # EEXISTS
+ # good
+ } else {
+ undef $result;
+ }
+ }
+ }
+ return $result;
+}
+
sub zt_registration($$) {
my $self = shift;
my $on = shift;
diff --git a/xpp/utils/zt_registration b/xpp/utils/zt_registration
index 6ed388f..a1cb8ee 100755
--- a/xpp/utils/zt_registration
+++ b/xpp/utils/zt_registration
@@ -5,7 +5,9 @@
# This program is free software; you can redistribute and/or
# modify it under the same terms as Perl itself.
#
-#use strict;
+# $Id$
+#
+use strict;
BEGIN { my $dir = $0; $dir =~ s:/[^/]+$::; unshift(@INC, "$dir", "$dir/zconf"); }
use Zaptel;
@@ -19,36 +21,43 @@ sub usage {
@ARGV == 0 or @ARGV == 1 or usage;
my $on = shift;
+my $verbose = 0;
+my $should_output = 1;
if(defined($on)) { # Translate to booleans
$on = uc($on);
$on =~ /^(ON|OFF|1|0)$/ or usage;
$on = ($on eq 'ON') ? 1 : 0;
+ $should_output = 0 unless $verbose;
}
sub state2str($) {
return (shift)?"on":"off";
}
+sub myprintf {
+ printf @_ if $should_output;
+}
+
my @spans = Zaptel::spans;
foreach my $xbus (Zaptel::Xpp::xbuses('SORT_CONNECTOR')) {
- printf "%-10s\t\t%s\n", $xbus->name, $xbus->connector;
+ myprintf "%-10s\t\t%s\n", $xbus->name, $xbus->connector;
next unless $xbus->status eq 'CONNECTED';
foreach my $xpd ($xbus->xpds()) {
my $prev = $xpd->zt_registration($on);
- printf "\t%-10s: ", $xpd->fqn;
+ myprintf "\t%-10s: ", $xpd->fqn;
if(!defined($on)) { # Query only
my ($span) = grep { $_->name eq $xpd->fqn } @spans;
my $spanstr = ($span) ? ("Span " . $span->num) : "";
- printf "%s %s\n", state2str($prev), $spanstr;
+ myprintf "2 %s %s\n", state2str($prev), $spanstr ;
next;
}
if(!defined($prev)) { # Failure
printf "Failed %s\n", $!;
next;
}
- printf("%3s ==> %3s\n", state2str($prev), state2str($on));
+ myprintf "3 %3s ==> %3s\n", state2str($prev), state2str($on);
}
}