diff options
Diffstat (limited to 'xpp')
-rw-r--r-- | xpp/Makefile | 6 | ||||
-rwxr-xr-x | xpp/astribank_hook | 82 | ||||
-rw-r--r-- | xpp/astribank_is_starting.8 | 100 | ||||
-rw-r--r-- | xpp/astribank_is_starting.c | 190 | ||||
-rwxr-xr-x | xpp/twinstar_hook | 71 | ||||
-rwxr-xr-x | xpp/waitfor_xpds | 24 | ||||
-rw-r--r-- | xpp/xpp_fxloader | 3 |
7 files changed, 408 insertions, 68 deletions
diff --git a/xpp/Makefile b/xpp/Makefile index 9409e97..13d8e21 100644 --- a/xpp/Makefile +++ b/xpp/Makefile @@ -65,8 +65,9 @@ TARGETS += fpga_load \ astribank_tool \ astribank_hexload \ astribank_allow \ + astribank_is_starting \ test_parse -PROG_INSTALL += fpga_load astribank_tool astribank_hexload astribank_allow +PROG_INSTALL += fpga_load astribank_tool astribank_hexload astribank_allow astribank_is_starting endif ifneq (,$(PERLLIBDIR)) PROG_INSTALL += $(PERL_SCRIPTS) @@ -113,6 +114,9 @@ astribank_tool: $(ABTOOL_OBJS) astribank_allow: $(ABALLOW_OBJS) $(CC) -L. -o $@ $(ABALLOW_OBJS) $(EXTRA_LIBS) -lusb +astribank_is_starting: astribank_is_starting.o + $(CC) -L. -o $@ $^ $(EXTRA_LIBS) + fpga_load.o: CFLAGS+=-D_GNU_SOURCE # We use memrchr() test_parse: test_parse.o hexfile.o diff --git a/xpp/astribank_hook b/xpp/astribank_hook index 9510f7b..dc55d14 100755 --- a/xpp/astribank_hook +++ b/xpp/astribank_hook @@ -11,11 +11,76 @@ LOGGER="logger -i -t '$me'" ## If you wish to trace this script: #exec 2> "/tmp/${me}_$XBUS_NAME" 1>&2 +# Our directory in the beginning, so we can use local lab setup PATH="$dir:/usr/sbin:/sbin:/usr/bin:/bin" set -e -echo "starting($ACTION): '$*'" | $LOGGER +[ -r /etc/dahdi/init.conf ] && . /etc/dahdi/init.conf + +# For lab testing +liveconf="$dir/liveconf/dahdi" + +if [ -d "$liveconf" ]; then + dahdi_conf="$liveconf" +else + dahdi_conf="/etc/dahdi" +fi + +export XPPORDER_CONF="$dahdi_conf/xpp_order" +if [ ! -r "$XPPORDER_CONF" ]; then + ( + echo "Skip($ACTION): No '$XPPORDER_CONF'" + echo "Removing uneeded startup semaphore" + astribank_is_starting -v -r 2>&1 + ) 2>&1 | $LOGGER + exit 0 +fi +export DAHDI_CFG_CMD="dahdi_cfg -c $dahdi_conf/system.conf" +export CALLED_FROM_ATRIBANK_HOOK=yes + +clean_lines() { + sed -e 's/#.*//' -e 'y/\t/ /' -e 's/^ *//' -e 's/ *$//' "$XPPORDER_CONF" +} + +matched_devices() { + ready=`grep -H READY /sys/bus/astribanks/devices/*/xbus_state | sed 's,/xbus_state.*,,'` + for dev in $ready + do + label=`cat "$dev/label"` + connector=`cat "$dev/connector"` + xbus=`echo "$dev" | sed 's,.*/,,'` + lineno=`clean_lines | egrep -n "^${label}$|^@${connector}$" | cut -d: -f1` + if [ "$lineno" != "" ]; then + #echo "$xbus: $XPPORDER_CONF:$lineno -- Match ${label} @${connector}" | $LOGGER + echo -e "${xbus}\t${label}" + else + echo "${xbus}: ${label} @${connector} not found in $XPPORDER_CONF: Ignore($ACTION)" | $LOGGER + fi + done +} + +NUM_WANTED=`clean_lines | sed '/^$/d' | wc -l` +NUM_GOOD=`matched_devices | wc -l` + +start_dahdi() { + script=/etc/init.d/dahdi + if [ "$XPP_HOTPLUG_DAHDI" = yes ]; then + echo "Starting $script." + "$script" start | logger -i -t "$script" + status=$? + echo "Status($script): $status" + else + echo "$0: Skip($script): No XPP_HOTPLUG_DAHDI=yes in /etc/dahdi/init.conf" + exit 0 + fi + if [ -x "$dir/twinstar_hook" ]; then + "$dir/twinstar_hook" + fi + # Finished astribanks + echo "Removing semaphore" + astribank_is_starting -v -r +} case "$ACTION" in add) @@ -23,13 +88,20 @@ add) remove) ;; online) - if [ -x "$dir/twinstar_hook" ]; then - "$dir/twinstar_hook" + echo "$ACTION($XBUS_NAME): $NUM_GOOD/$NUM_WANTED from $XPPORDER_CONF" | $LOGGER + if [ "$NUM_GOOD" -eq "$NUM_WANTED" ]; then + echo "START-DAHDI: Total $NUM_GOOD online." | $LOGGER + # Fork services + start_dahdi < /dev/null 2>&1 | $LOGGER & fi ;; offline) - if [ -x "$dir/twinstar_hook" ]; then - "$dir/twinstar_hook" + echo "$ACTION($XBUS_NAME): $NUM_GOOD/$NUM_WANTED from $XPPORDER_CONF" | $LOGGER + if [ "$NUM_GOOD" -eq 0 ]; then + echo "All Astribanks offline" | $LOGGER + if [ -x "$dir/twinstar_hook" ]; then + "$dir/twinstar_hook" + fi fi ;; *) diff --git a/xpp/astribank_is_starting.8 b/xpp/astribank_is_starting.8 new file mode 100644 index 0000000..55db6f6 --- /dev/null +++ b/xpp/astribank_is_starting.8 @@ -0,0 +1,100 @@ +.TH "ASTRIBANK_IS_STARTING" "8" "16 August 2009" "" "" + +.SH NAME +astribank_is_starting \- Mark / check is a Xorcom Astribank (xpp) is starting +.SH SYNOPSIS +.B astribank_is_starting [-d] [-v] [-t \fItimeout\fB] <-a|-r|-w> + +.B astribank_is_starting [-d] [-v] + +.B astribank_is_starting -h + +.SH DESCRIPTION +.B astribank_is_starting +is an internal tool used by various xpp scripts to mark that there may +be an Astribank device currently initializing, and to check for that mark. + +Technically the mark is a SysV semaphore. + +.SH OPTIONS +.B -a +.RS +.B Add. +Set the mark. Should return 0 unless there's an error. +.RE + +.B -r +.RS +.B Remove. +Reset the mark. Should return 0 unless there's an error. +.RE + +.BI -t timeout +.RS +.B Timeout. +Set the timeout value for the \fB-w\fR option. Default is 60 seconds. +.RE + +.B -w +.RS +.B Wait. +Wait for mark to be reset. Should return 0 unless there's an error. +.RE + +Without -a or -r: return 0 if the mark has been set, or a non-zero value +otherwise. + +.B -d +.RS +Print debug information to stderr. +.RE + +.B -v +.RS +Verbose execution. +.RE + +.B -h +.RS +Displays usage message. +.RE + +.SH FILES +.B /proc/sysvipc/sem +.RS +If set, the astribank should appear there with the ID 11211168 (0xAB11A0). +Naturally the ID (or rather, the usage of a semaphore in the first place) +is an implementation detail that may change. +.RE + +.SH NOTES +.B astribank_is_starting +is used to mark the fact that an Astribank may be currently reenumerating +(technically: distonnecting and connecting as a new USB device) after +loading the firmware. Thus the script that loads the firmware +(/usr/share/dahdi/xpp_fxloader) uses this utility to set the mark. + +The mark is reset by /usr/share/dahdi/waitfor_xpds , which is typically +run by the DAHDI init script and waits for all Astribanks to finish +loading. + +Q: Why do you use a semaphore? + +A: because, unlike the filesystem, it is writable at any given time. + +.SH BUGS +Option ordering matter. The \fB-v\fR and \fB-d\fR options should preceed +the actions (\fB-a\fR, \fB-r\fR and \fB-w\fR). +The \fB-t\fItimeout\fR option should preceed the \fB-w\fR option. + +.SH SEE ALSO +semctl(3) + +.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/astribank_is_starting.c b/xpp/astribank_is_starting.c new file mode 100644 index 0000000..578ea9b --- /dev/null +++ b/xpp/astribank_is_starting.c @@ -0,0 +1,190 @@ +#define _GNU_SOURCE /* 2.3 and later will define this from autoconfig.h */ +#include <sys/types.h> +#include <sys/ipc.h> +#include <sys/sem.h> +#include <errno.h> +#include <getopt.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <time.h> + +static char *progname; +static const key_t key_astribanks = 0xAB11A0; +static int debug; +static int verbose; +static int timeout_seconds = 60; + + +static void usage(void) +{ + fprintf(stderr, "Usage: %s [-d] [-t <seconds>] [-a|-r|-w]\n", progname); + exit(1); +} + +static int absem_get(int createit) +{ + int flags = (createit) ? IPC_CREAT | 0644 : 0; + int absem; + + if((absem = semget(key_astribanks, 1, flags)) < 0) + absem = -errno; + return absem; +} + +static int absem_touch(void) +{ + int absem; + + if((absem = absem_get(1)) < 0) { + perror(__FUNCTION__); + return absem; + } + if(semctl(absem, 0, SETVAL, 0) < 0) { + perror("SETVAL"); + return -errno; + } + if(debug) + fprintf(stderr, "%s: touched absem\n", progname); + if(verbose) + printf("Astribanks initialization is starting\n"); + return 0; +} + +static int absem_remove(void) +{ + int absem; + + if((absem = absem_get(0)) < 0) { + if(absem == -ENOENT) { + if(debug) + fprintf(stderr, "%s: absem already removed\n", progname); + return 0; + } + perror(__FUNCTION__); + return absem; + } + if(semctl(absem, 0, IPC_RMID, 0) < 0) { + perror("RMID"); + return -errno; + } + if(debug) + fprintf(stderr, "%s: removed absem\n", progname); + if(verbose) + printf("Astribanks initialization is done\n"); + return 0; +} + +static int absem_wait(void) +{ + int absem; + struct sembuf sops; + long now; + long start_wait; + struct timespec timeout; + + if((absem = absem_get(0)) < 0) { + perror(__FUNCTION__); + return absem; + } + sops.sem_num = 0; + sops.sem_op = -1; + sops.sem_flg = 0; + start_wait = time(NULL); + timeout.tv_sec = timeout_seconds; + timeout.tv_nsec = 0; + if(semtimedop(absem, &sops, 1, &timeout) < 0) { + switch(errno) { + case EIDRM: /* Removed -- OK */ + break; + case EAGAIN: /* Timeout -- Report */ + fprintf(stderr, "Astribanks waiting timed out\n"); + return -errno; + default: /* Unexpected errors */ + perror("semop"); + return -errno; + } + /* fall-thgough */ + } + now = time(NULL); + if(debug) + fprintf(stderr, "%s: waited on absem %ld seconds\n", progname, now - start_wait); + if(verbose) + printf("Finished after %ld seconds\n", now - start_wait); + return 0; +} + +static int absem_detected(void) +{ + int absem; + + if((absem = absem_get(0)) < 0) { + if(debug) + fprintf(stderr, "%s: absem does not exist\n", progname); + return absem; + } + if(debug) + fprintf(stderr, "%s: absem exists\n", progname); + if(verbose) + printf("Astribanks are initializing...\n"); + return 0; +} + +int main(int argc, char *argv[]) +{ + const char options[] = "dvarwt:h"; + int val; + + progname = argv[0]; + while (1) { + int c; + int t; + + c = getopt (argc, argv, options); + if (c == -1) + break; + + switch (c) { + case 'd': + debug++; + break; + case 'v': + verbose++; + break; + case 't': + t = atoi(optarg); + if(t <= 0) { + fprintf(stderr, + "%s: -t expect a positive number of seconds: '%s'\n", + progname, optarg); + usage(); + } + timeout_seconds = t; + break; + case 'a': + if((val = absem_touch()) < 0) { + fprintf(stderr, "%s: Add failed: %d\n", progname, val); + return 1; + } + return 0; + case 'r': + if((val = absem_remove()) < 0) { + fprintf(stderr, "%s: Remove failed: %d\n", progname, val); + return 1; + } + return 0; + case 'w': + if((val = absem_wait()) < 0) { + fprintf(stderr, "%s: Wait failed: %d\n", progname, val); + return 1; + } + return 0; + case 'h': + default: + fprintf(stderr, "Unknown option '%c'\n", c); + usage(); + } + } + val = absem_detected(); + return (val == 0) ? 0 : 1; +} diff --git a/xpp/twinstar_hook b/xpp/twinstar_hook index e463218..6818c85 100755 --- a/xpp/twinstar_hook +++ b/xpp/twinstar_hook @@ -49,74 +49,25 @@ PATH="$dir:/usr/sbin:/sbin:/usr/bin:/bin" set -e -# For lab testing -liveconf="$dir/liveconf/dahdi" - -if [ -d "$liveconf" ]; then - dahdi_conf="$liveconf" -else - dahdi_conf="/etc/dahdi" -fi - -export XPPORDER_CONF="$dahdi_conf/xpp_order" -if [ ! -r "$XPPORDER_CONF" ]; then - echo "Skip($ACTION): No '$XPPORDER_CONF'" | $LOGGER - exit 0 -fi -SYSTEMCONF="$dahdi_conf/system.conf" - -TWS_DIR="/var/tmp" -TWS_PREFIX="$TWS_DIR/twinstar-" -LABELFILE="/sys/$DEVPATH/label" export XBUS_SORT='SORT_LABEL' -echo "starting($ACTION): setup from $XPPORDER_CONF" | $LOGGER -STAMP="${TWS_PREFIX}${XBUS_NAME}" -TWS_TOTAL=`sed -e 's/#.*//' -e '/^[ ]*$/d' -e 'y/\t/ /' "$XPPORDER_CONF" | wc -l` - case "$ACTION" in online) - if [ ! -f "$LABELFILE" ]; then - echo "Missing labelfile '$LABELFILE'" | $LOGGER - exit 1 - fi - LABEL=`cat $LABELFILE` - TWS_LINE=`awk "/^$LABEL/" $XPPORDER_CONF` - if [ "$TWS_LINE" = "" ]; then - echo "online($XBUS_NAME): '$LABEL' is not in '$XPPORDER_CONF'" | $LOGGER - exit 1 - fi - echo "$LABEL" > "$STAMP" - HOW_MANY=`ls ${TWS_PREFIX}* | wc -l` - echo "online($XBUS_NAME): $LABEL (${HOW_MANY}/${TWS_TOTAL})" | $LOGGER + echo "$ACTION($XBUS_NAME): " | $LOGGER twinstar enable-wd - if [ "$HOW_MANY" -eq "$TWS_TOTAL" ]; then - echo "online: GOT ALL $TWS_TOTAL" | $LOGGER - dahdi_registration on - dahdi_registration 2>&1 | tr '\t' ' ' | $LOGGER - echo "Using '$SYSTEMCONF'" 2>&1 | $LOGGER - dahdi_cfg -v -c "$SYSTEMCONF" 2>&1 | $LOGGER - sleep 1 # Just for visual effect - asterisk -rx 'module load chan_dahdi.so' 2>&1 | $LOGGER - xpp_blink bzzt xpd "$XBUS_NUM" - ports=`twinstar ports` - if [ "$ports" = 0 ]; then - play /usr/share/dahdi/primary-pbx-is-ready.wav || : - elif [ "$ports" = 1 ]; then - play /usr/share/dahdi/backup-pbx-is-ready.wav || : - fi - echo "online: READY" | $LOGGER + sleep 1 # Just for visual effect + asterisk -rx 'module load chan_dahdi.so' 2>&1 | $LOGGER + xpp_blink bzzt xpd "$XBUS_NUM" + ports=`twinstar ports` + if [ "$ports" = 0 ]; then + play /usr/share/dahdi/primary-pbx-is-ready.wav || : + elif [ "$ports" = 1 ]; then + play /usr/share/dahdi/backup-pbx-is-ready.wav || : fi + echo "online: READY" | $LOGGER ;; offline) - LABEL=`cat $STAMP` - TWS_LINE=`awk "/^$LABEL/" $XPPORDER_CONF` - rm -f "$STAMP" - if [ "$TWS_LINE" = "" ]; then - echo "offline($XBUS_NAME): $LABEL is not in $XPPORDER_CONF" | $LOGGER - exit 1 - fi - echo "offline($XBUS_NAME): $LABEL" | $LOGGER + echo "$ACTION($XBUS_NAME): " | $LOGGER twinstar disable-wd # If we want to disconnect everybody twinstar jump diff --git a/xpp/waitfor_xpds b/xpp/waitfor_xpds index 71b7dfc..6bee5f2 100755 --- a/xpp/waitfor_xpds +++ b/xpp/waitfor_xpds @@ -29,6 +29,8 @@ set -e mydir=`dirname $0` PATH="${mydir}:${PATH}" +[ -r /etc/dahdi/init.conf ] && . /etc/dahdi/init.conf + ab_list() { # Only check /sys info (don't use /proc anymore). ab=`find /sys/bus/astribanks/devices/xbus-*/ -name waitfor_xpds 2> /dev/null || :` @@ -40,7 +42,14 @@ if ! dahdi_hardware="`which dahdi_hardware 2>/dev/null`"; then echo >&2 "$0: Missing dahdi_hardware" exit 0 fi -if [ "`$dahdi_hardware | grep xpp_usb`" = "" ]; then +if ! astribank_is_starting="`which astribank_is_starting 2>/dev/null`"; then + echo >&2 "$0: Missing astribank_is_starting" + exit 0 +fi +if [ "`$dahdi_hardware | grep xpp_usb`" != "" ]; then + astribank_is_starting -v -a +fi +if ! astribank_is_starting; then exit 0 fi @@ -60,7 +69,7 @@ done echo "" # Wait for device to stabilize and XPD's to finish initalizations -echo 1>&2 "Astribanks initalization " +echo 1>&2 "Astribanks initializing spans" while if ! ab=`ab_list`; then exit 1 @@ -70,3 +79,14 @@ do oldab="$ab" cat $ab done + +if [ "$XPP_HOTPLUG_DAHDI" = yes ]; then + if [ "$CALLED_FROM_ATRIBANK_HOOK" = '' ]; then + # Now we can wait until the hotplug run would remove the semaphore + echo -n 1>&2 "Other DAHDI initializations... " + astribank_is_starting -v -w 1>&2 + fi +else + # Non-hotplug -- Sequential initialization, remove semaphore + astribank_is_starting -v -r 1>&2 +fi diff --git a/xpp/xpp_fxloader b/xpp/xpp_fxloader index 2f42126..790b0fd 100644 --- a/xpp/xpp_fxloader +++ b/xpp/xpp_fxloader @@ -262,6 +262,9 @@ usage() { echo "$0 help : this text." } +# We have a potential astribank +astribank_is_starting -a + ######################### ## ## Manual run |