basic user-space for pinned-spans
authorOron Peled <oron.peled@xorcom.com>
Thu, 6 Oct 2011 19:03:00 +0000 (21:03 +0200)
committerRuss Meyerriecks <rmeyerriecks@digium.com>
Fri, 24 May 2013 21:58:15 +0000 (16:58 -0500)
handle_device is the basic script intended to be called from udev.

It will call span_types on the span to apply optional
/etc/dahdi/spantype.conf onfiguration settings that need to be applied
before assignment (currently "pri" port types: E1/T1/J1).

Next it assigns span numbers to spans: if configured in
/etc/dahdi/pinned-spans.conf - use those settings. If not: by the order
of loading.

span_types and span_assignments can also be used to report the settings
they are used to configure.

Signed-off-by: Oron Peled <oron.peled@xorcom.com>
Signed-off-by: Tzafrir Cohen <tzafrir.cohen@xorcom.com>
Signed-off-by: Russ Meyerriecks <rmeyerriecks@digium.com>

dahdi.rules [new file with mode: 0644]
dahdi_map [new file with mode: 0755]
doc/dahdi_map.8 [new file with mode: 0644]
handle_device [new file with mode: 0755]
pinned-spans.conf [new file with mode: 0644]
span_assignments [new file with mode: 0755]
span_types [new file with mode: 0755]
spantype.conf [new file with mode: 0644]

diff --git a/dahdi.rules b/dahdi.rules
new file mode 100644 (file)
index 0000000..ef08fd3
--- /dev/null
@@ -0,0 +1,3 @@
+# DAHDI devices with ownership/permissions for running as non-root
+SUBSYSTEM=="dahdi",            OWNER="asterisk", GROUP="asterisk", MODE="0660"
+SUBSYSTEM=="dahdi_devices",    RUN="/usr/share/dahdi/handle_device"
diff --git a/dahdi_map b/dahdi_map
new file mode 100755 (executable)
index 0000000..a95ebae
--- /dev/null
+++ b/dahdi_map
@@ -0,0 +1,39 @@
+#! /bin/sh
+#
+# Show a map of dahdi devices with the following fields:
+#  - spanno (or '-' if not assigned yet)
+#  - (vendor assigned) name
+#  - local spanno
+#  - hardware_id (or empty if none)
+#  - location (prefixed by '@')
+
+devbase="/sys/bus/dahdi_devices/devices"
+
+[ -d "$devbase" ] || {
+       echo >&2 "$0: Missing '$devbase' (Old driver?)"
+       exit 1
+}
+
+fmt="%-4s %-17s %-3s     %-12s %s\n"
+
+printf "$fmt" 'SPAN' 'NAME' '#' 'HARDWARE_ID' 'LOCATION'
+
+DEVICES=`echo $devbase/*`
+
+for device in $DEVICES
+do
+       hw_id=`cat "$device/hardware_id"`
+       location=`cd "$device" && pwd -P | sed 's,/sys/devices/,,'`
+       for local_spanno in `cut -d: -f1 "$device/spantype"`
+       do
+               span=`grep 2>/dev/null -Hw "$local_spanno" "$device/span-"*"/local_spanno" | \
+                       sed -e 's,/local_spanno:.*,,' -e 's,.*/,,'`
+               if [ "$span" != '' ]; then
+                       spanno=`echo $span | sed 's/^.*-//'`
+                       name=`cat 2>/dev/null "$device/$span/name"`
+               else
+                       spanno='-'
+               fi
+               printf "$fmt" "$spanno" "$name" "($local_spanno)" "[$hw_id]" "@$location"
+       done | sort -n
+done
diff --git a/doc/dahdi_map.8 b/doc/dahdi_map.8
new file mode 100644 (file)
index 0000000..80d5d8f
--- /dev/null
@@ -0,0 +1,48 @@
+.TH dahdi_test 8 "2013-05-24" 
+.SH "NAME" 
+dahdi_map \(em List hardware IDs and locations of DAHDI spans
+.SH "SYNOPSIS" 
+.B dahdi_map
+
+.SH DESCRIPTION 
+.B dahdi_map
+prints a list of hardware IDs and locations of any DAHDI span on the system
+(possibly not yet assigned).
+
+It takes no extra options or parameters.
+
+Example output:
+.EX
+SPAN NAME              #       HARDWARE_ID  LOCATION
+5    XBUS-00/XPD-00    (1)     [usb:INT06380] @pci0000:00/0000:00:10.4/usb1/1-3/xbus-00/astribanks:xbus-00
+6    XBUS-00/XPD-01    (2)     [usb:INT06380] @pci0000:00/0000:00:10.4/usb1/1-3/xbus-00/astribanks:xbus-00
+7    XBUS-00/XPD-02    (3)     [usb:INT06380] @pci0000:00/0000:00:10.4/usb1/1-3/xbus-00/astribanks:xbus-00
+8    XBUS-00/XPD-03    (4)     [usb:INT06380] @pci0000:00/0000:00:10.4/usb1/1-3/xbus-00/astribanks:xbus-00
+9    XBUS-00/XPD-04    (5)     [usb:INT06380] @pci0000:00/0000:00:10.4/usb1/1-3/xbus-00/astribanks:xbus-00
+10   XBUS-00/XPD-05    (6)     [usb:INT06380] @pci0000:00/0000:00:10.4/usb1/1-3/xbus-00/astribanks:xbus-00
+11   XBUS-00/XPD-06    (7)     [usb:INT06380] @pci0000:00/0000:00:10.4/usb1/1-3/xbus-00/astribanks:xbus-00
+12   XBUS-00/XPD-07    (8)     [usb:INT06380] @pci0000:00/0000:00:10.4/usb1/1-3/xbus-00/astribanks:xbus-00
+13   XBUS-00/XPD-10    (9)     [usb:INT06380] @pci0000:00/0000:00:10.4/usb1/1-3/xbus-00/astribanks:xbus-00
+14   XBUS-00/XPD-20    (10)     [usb:INT06380] @pci0000:00/0000:00:10.4/usb1/1-3/xbus-00/astribanks:xbus-00
+15   XBUS-00/XPD-30    (11)     [usb:INT06380] @pci0000:00/0000:00:10.4/usb1/1-3/xbus-00/astribanks:xbus-00
+16   XBUS-01/XPD-00    (1)     []           @pci0000:00/0000:00:10.4/usb1/1-4/xbus-01/astribanks:xbus-01
+1    XBUS-02/XPD-00    (1)     [usb:XILINX_4] @pci0000:00/0000:00:10.4/usb1/1-1/xbus-02/astribanks:xbus-02
+2    XBUS-02/XPD-10    (2)     [usb:XILINX_4] @pci0000:00/0000:00:10.4/usb1/1-1/xbus-02/astribanks:xbus-02
+3    XBUS-02/XPD-20    (3)     [usb:XILINX_4] @pci0000:00/0000:00:10.4/usb1/1-1/xbus-02/astribanks:xbus-02
+4    XBUS-02/XPD-30    (4)     [usb:XILINX_4] @pci0000:00/0000:00:10.4/usb1/1-1/xbus-02/astribanks:xbus-02
+.EE
+
+.SH FILES
+.B /sys/bus/dahdi_devices/devices
+.RS
+Information taken from that area in SysFS.
+.RE
+
+.SH SEE ALSO 
+dahdi_cfg(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. 
diff --git a/handle_device b/handle_device
new file mode 100755 (executable)
index 0000000..180a163
--- /dev/null
@@ -0,0 +1,41 @@
+#! /bin/sh
+#
+# /usr/share/dahdi/handle_device
+#
+# Called by UDEV when a span goes online/offline to assign spans
+
+me=`basename $0`
+dir=`dirname $0`
+LOGGER="logger -i -t '$me'"
+NAME=`basename "$DEVPATH" | tr -c 'A-Za-z0-9-' '_'`
+
+# Always redirect stderr somewhere, otherwise the shell script will die
+# when it tries to do I/O related stuff on closed file descriptor.
+# Our default is to throw it down the bit-bucket.
+exec 2> /dev/null
+# If you wish to trace this script:
+#exec 2> "/tmp/${me}.$NAME" 1>&2
+#exec 2> /dev/console
+
+# Our directory in the beginning, so we can use local lab setup
+PATH="$dir:/usr/sbin:/sbin:/usr/bin:/bin"
+
+set -e
+
+echo >&2 "$0($ACTION): DEBUG($# args): '$*'"
+
+case "$ACTION" in
+add)
+       echo "$ACTION: $DEVPATH" | $LOGGER
+       # FIXME: need a way to add custom environment here:
+       #export DAHDICONFDIR="/tmp/xortel/dahdi"
+       span_types set "/sys/$DEVPATH" 2>&1 | $LOGGER
+       span_assignments add "/sys/$DEVPATH" 2>&1 | $LOGGER
+       ;;
+remove)
+       echo "$ACTION: $DEVPATH" | $LOGGER
+       ;;
+*)
+       echo "UNHANDLED: $ACTION: $DEVPATH" | $LOGGER
+       ;;
+esac
diff --git a/pinned-spans.conf b/pinned-spans.conf
new file mode 100644 (file)
index 0000000..a9145bb
--- /dev/null
@@ -0,0 +1,56 @@
+#
+# /etc/dahdi/pinned-spans.conf:
+#
+# This file assigns span and channel numbers to dahdi devices
+#
+# Built as a table keyed by <id>:
+#  <id>    <spanspec>....
+#
+# Where:
+#  * The <id> field may be either:
+#         hardware_id
+#         @location
+#  * Shell-style globbing is allowed for the <id> field
+#  * There may one or more of <spanspec>
+#  * Each <spanspec> is composed as:
+#    <local_spanno>:<assigned_spanno>:<base_channo>
+#
+# Examples:
+
+# Astribank with two spans:
+#    FXS * 8 channels + 4 digital inputs 2 digital outputs
+#    FXO * 8 channels
+#usb:QA-1              1:1:1
+#usb:QA-1              2:2:15
+
+# Same Astribank in one-liner
+#usb:QA-1              1:1:1 2:2:15
+
+# Astribank with 4*PRI spans and 3*FXS*8 spans
+# Note that channels are NOT globally contigous
+# each span get its own 50 numbers. Also, skip
+# Channel number 250...
+#usb:INT03165          1:1:1   # E1
+#usb:INT03165          2:2:51  # E1
+#usb:INT03165          3:3:151 # E1
+#usb:INT03165          4:4:201 # E1
+#usb:INT03165          5:5:301 # FXS * 8 channels
+#usb:INT03165          6:6:351 # FXS * 8 channels
+#usb:INT03165          7:7:401 # FXS * 8 channels
+
+# Alternatively -- all in one-line
+#usb:INT03165          1:1:1 2:2:51 3:3:151 4:4:201 5:5:301 6:6:351 7:7:401
+
+# Astribank with 4*BRI without hardware_id :-(
+# We use the location on the bus (ie: where it is physically
+# located). Note the '@' prefix that indicate the location key.
+#@pci0000:00/0000:00:03.3/usb1/1-6/xbus-01/astribanks:xbus-01  1:1:50
+#@pci0000:00/0000:00:03.3/usb1/1-6/xbus-01/astribanks:xbus-01  2:2:100
+#@pci0000:00/0000:00:03.3/usb1/1-6/xbus-01/astribanks:xbus-01  3:3:150
+#@pci0000:00/0000:00:03.3/usb1/1-6/xbus-01/astribanks:xbus-01  4:4:200
+
+# Same configuration with globbing:
+#@*/usb1/1-6/* 1:1:50
+#@*/usb1/1-6/* 2:2:100
+#@*/usb1/1-6/* 3:3:150
+#@*/usb1/1-6/* 4:4:200
diff --git a/span_assignments b/span_assignments
new file mode 100755 (executable)
index 0000000..0f4e006
--- /dev/null
@@ -0,0 +1,193 @@
+#! /bin/sh
+#
+# /usr/share/dahdi/span_assignments:
+#
+# this script can be used both from udev and
+# from the command line to assign/unassign and list
+# current assignments.
+#
+# The first argument is an action:
+#   "add" to assign (spans which are not already assigned)
+#   "remove" to unassign (spans which are not already unassigned)
+#   "list" to show all spans (with/without assignments)
+#
+# Without further arguments, it operates on all existing spans
+# With one or more sysfs dahdi_devices it is limited to those.
+#
+# Examples:
+#    span_assignments list
+#    span_assignments add      # all
+#    span_assignments add /sys/bus/dahdi_devices/devices/astribanks:xbus-00
+#    span_assignments remove   # all
+#
+
+devbase='/sys/bus/dahdi_devices/devices'
+DAHDICONFDIR="${DAHDICONFDIR:-/etc/dahdi}"
+pinned_spans_conf="$DAHDICONFDIR/pinned-spans.conf"
+
+usage() {
+       echo >&2 "Usage: $0 {add|remove|list} [devpath ...]"
+       exit 1
+}
+
+if [ "$#" -eq 0 ]; then
+       usage
+fi
+action="$1"
+shift
+
+if [ ! -d "$devbase" ]; then
+       echo >&2 "$0: Missing '$devbase' (DAHDI driver unloaded?)"
+       exit 1
+fi
+
+# Use given devices or otherwise, all existing devices
+if [ "$#" -gt 0 ]; then
+       DEVICES="$@"
+else
+       DEVICES=`echo $devbase/*`
+fi
+
+show_devices() {
+
+       for device in $DEVICES
+       do
+               hw_id=`cat "$device/hardware_id"`
+               location=`cd "$device" && pwd -P | sed 's,/sys/devices/,,'`
+               for local_spanno in `cut -d: -f1 "$device/spantype"`
+               do
+                       span=`grep 2>/dev/null -Hw "$local_spanno" "$device/span-"*"/local_spanno" | \
+                               sed -e 's,/local_spanno:.*,,' -e 's,.*/,,'`
+                       if [ "$span" != '' ]; then
+                               spanno=`echo $span | sed 's/^.*-//'`
+                               name=`cat 2>/dev/null "$device/$span/name"`
+                               basechan=`cat 2>/dev/null "$device/$span/basechan"`
+                       else
+                               spanno='-'
+                               basechan='-'
+                       fi
+                       printf "%-4s %-12s %s\n" "$local_spanno:$spanno:$basechan" "[$hw_id]" "@$location"
+               done | sort -n
+       done
+}
+
+dump_config() {
+
+       for device in $DEVICES
+       do
+               hw_id=`cat "$device/hardware_id"`
+               location=`cd "$device" && pwd -P | sed 's,/sys/devices/,,'`
+               if [ "$hw_id" != '' ]; then
+                       id="$hw_id"
+               else
+                       id="@$location"
+               fi
+               for local_spanno in `cut -d: -f1 "$device/spantype"`
+               do
+                       span=`grep 2>/dev/null -Hw "$local_spanno" "$device/span-"*"/local_spanno" | \
+                               sed -e 's,/local_spanno:.*,,' -e 's,.*/,,'`
+                       if [ "$span" != '' ]; then
+                               spanno=`echo $span | sed 's/^.*-//'`
+                               name=`cat 2>/dev/null "$device/$span/name"`
+                               basechan=`cat 2>/dev/null "$device/$span/basechan"`
+                       else
+                               spanno='-'
+                       fi
+                       printf "%-30s %s\n" "$id" "$local_spanno:$spanno:$basechan"
+               done | sort -n
+       done
+}
+
+unassign_all_spans() {
+       for device in $DEVICES
+       do
+               find "$device" -follow -maxdepth 1 -name 'span-*' -type d | \
+                       sort | while read spandir; do
+                       local_spanno=`cat "$spandir/local_spanno"`
+                       echo "unassign $device $local_spanno"
+                       if ! echo "$local_spanno" > "$device/unassign_span"; then
+                               echo >&2 "$0: failed unassigning '$local_spanno' in '$device'"
+                       fi
+               done
+       done
+}
+
+# Allow comments and empty lines in config file
+filter_conf() {
+       sed -e 's/#.*//' -e '/^[ \t]*$/d' "$pinned_spans_conf"
+}
+
+# Beware of special characters in attributes
+attr_clean() {
+       cat "$1" | tr -d '\n' | tr '!' '/' | tr -c 'a-zA-Z0-9/:.-' '_'
+}
+
+assign_device_spans() {
+       device="$1"
+       for s in $spanspecs
+       do
+               local_spanno=`echo "$s" | cut -d: -f1`
+               spanno=`echo "$s" | cut -d: -f2`
+               span="$device/span-$spanno"
+               if [ -d "$span" ]; then
+                       span_local_spanno=`cat "$span/local_spanno"`
+                       if [ "$span_local_spanno" != "$local_spanno" ]; then
+                               echo "WARNING: $span_local_spanno != $local_spanno"
+                       fi
+                       echo "$device [$local_spanno] already assigned to $spanno. Skipping..."
+                       continue
+               fi
+               echo "assign $device: $s"
+               if ! echo "$s" > "$device/assign_span"; then
+                       echo >&2 "$0: failed assigning '$s' to '$device'"
+               fi
+       done
+}
+
+match_device() {
+       device="$1"
+       location='@'`cd "$device" && pwd -P | sed 's,/sys/devices/,,'`
+       hardware_id=`attr_clean "$device/hardware_id"`
+       filter_conf | while read id spanspecs
+       do
+               # We use case to enable shell-style globbing in configuration
+               case "$location" in
+               $id)
+                       #echo "match location($id ~ $location): $spanspecs"
+                       assign_device_spans "$device"
+                       ;;
+               esac
+               # We use case to enable shell-style globbing in configuration
+               case "$hardware_id" in
+               $id)
+                       #echo "match hardware_id([$id] ~ $hardware_id): $spanspecs"
+                       assign_device_spans "$device"
+                       ;;
+               esac
+       done
+}
+
+assign_devices() {
+       for device in $DEVICES
+       do
+               match_device "$device"
+       done
+}
+
+case "$action" in
+list)
+       show_devices
+       ;;
+dump)
+       dump_config
+       ;;
+add)
+       assign_devices
+       ;;
+remove)
+       unassign_all_spans
+       ;;
+*)
+       usage
+       ;;
+esac
diff --git a/span_types b/span_types
new file mode 100755 (executable)
index 0000000..cf7c70d
--- /dev/null
@@ -0,0 +1,160 @@
+#! /bin/sh
+#
+# /usr/share/dahdi/span_types:
+#
+# this script can be used both from udev and
+# from the command line for spantype management.
+#
+# It use a configuration file /etc/dahdi/spantype.conf
+# (the format is documented inside this file)
+#
+# The first argument is an action:
+#   "list" to show existing E1/T1/J1 types
+#   "dump" the same, but in a format (almost) suitable for
+#          the configuration file
+#          FIXME: we currently don't have the base channo in sysfs.
+#   "set"  actually write the setting to the driver
+#
+# Examples:
+#    span_types list
+#    span_types dump
+#    span_types set    # all
+#    span_types set /sys/bus/dahdi_devices/devices/astribanks:xbus-00
+#
+
+
+devbase='/sys/bus/dahdi_devices/devices'
+DAHDICONFDIR="${DAHDICONFDIR:-/etc/dahdi}"
+spantype_conf="$DAHDICONFDIR/spantype.conf"
+
+usage() {
+       echo >&2 "Usage: $0 {list|dump|set} [devpath ...]"
+       exit 1
+}
+
+if [ "$#" -eq 0 ]; then
+       usage
+fi
+action="$1"
+shift
+
+# Use given devices or otherwise, all existing devices
+if [ "$#" -gt 0 ]; then
+       DEVICES="$@"
+else
+       DEVICES=`echo $devbase/*`
+fi
+
+show_spantypes() {
+       for device in $DEVICES
+       do
+               hw_id=`cat "$device/hardware_id"`
+               location='@'`cd "$device" && pwd -P | sed 's,/sys/devices/,,'`
+               cat "$device/spantype" | while read st; do
+                       printf "%-10s %-20s %s\n" "$st" "[$hw_id]" "$location"
+               done | sort -n
+       done
+}
+
+dump_config() {
+       fmt="%-65s %s\n"
+       echo "# Map of dahdi_devices to span types for E1/T1/J1"
+       printf "$fmt" '# @location/hardware_id' 'span_type'
+       for device in $DEVICES
+       do
+               hw_id=`cat "$device/hardware_id"`
+               location='@'`cd "$device" && pwd -P | sed 's,/sys/devices/,,'`
+               if [ -n "$hw_id" ]; then
+                       id="$hw_id"
+               else
+                       id="$location"
+               fi
+               cat "$device/spantype" | while read st; do
+                       case "$st" in
+                       *:[ETJ]1)
+                               printf "$fmt" "$id" "$st"
+                               ;;
+                       esac
+               done | sort -n
+       done
+}
+
+# Allow comments and empty lines in config file
+filter_conf() {
+       sed -e 's/#.*//' -e '/^[ \t]*$/d' "$spantype_conf"
+}
+
+conf_spans() {
+       hw_id="$1"
+       location="$2"
+       filter_conf | (
+               # Collect device spans
+               # in a subshell, so $SPANS is not lost
+               SPANS=''
+               while read id spans; do
+                       # GLOBBING
+                       case "$location" in
+                       $id)
+                               #echo >&2 "match($id): $spans"
+                               SPANS="$SPANS $spans"
+                               ;;
+                       esac
+                       case "$hw_id" in
+                       $id)
+                               #echo >&2 "match([$id]): $spans"
+                               SPANS="$SPANS $spans"
+                               ;;
+                       esac
+               done
+               echo "$SPANS"
+       )
+}
+
+# Beware of special characters in attributes
+attr_clean() {
+       cat "$1" | tr -d '\n' | tr '!' '/' | tr -c 'a-zA-Z0-9/:.-' '_'
+}
+
+device_set_spantype() {
+       device="$1"
+       attr_file="$device/spantype"
+       hw_id=`attr_clean "$device/hardware_id"`
+       location='@'`cd "$device" && pwd -P | sed 's,/sys/devices/,,'`
+       spanspecs=`conf_spans "$hw_id" "$location"`
+       echo >&2 "MATCHED($device): $spanspecs"
+       cut -d: -f1 "$attr_file" | while read spanno; do
+                       for sp in $spanspecs
+                       do
+                               s=`echo "$sp" | cut -d: -f1`
+                               v=`echo "$sp" | cut -d: -f2`
+                               case "$spanno" in
+                               $s)
+                                       #echo >&2 "conf($attr_file): $spanno:$v"
+                                       echo "$spanno:$v" > "$attr_file"
+                                       ;;
+                               esac
+                       done
+               done
+}
+
+set_spantypes() {
+       for device in $DEVICES
+       do
+               device_set_spantype "$device"
+       done
+}
+
+case "$action" in
+list)
+       show_spantypes
+       ;;
+dump)
+       dump_config
+       ;;
+set)
+       set_spantypes
+       ;;
+*)
+       usage
+       ;;
+esac
diff --git a/spantype.conf b/spantype.conf
new file mode 100644 (file)
index 0000000..e639fe5
--- /dev/null
@@ -0,0 +1,27 @@
+#
+# /etc/dahdi/spantype.conf: Set E1/T1/J1 per-device
+#
+# Built as a table of two columns:
+#  <id>    <local_spanno>:<type>
+#
+# Where:
+#  * The <id> field may be either:
+#         hardware_id
+#         @location
+#  * The <local_spanno> is the relative span number 
+#    in the device (starting from 1)
+#    In this filed globbing rules apply. E.g:
+#        - * are all the spans in this device
+#        - [12] are the first two spans in this device
+#  * The <type> may be E1, T1 or J1
+#
+# Examples:
+#  Set the first two spans of a specific Astribank to T1
+#usb:000156 [12]:T1
+
+#  Set all spans of another Astribank to T1
+#usb:INT03165          *:E1
+
+#  Set the first two spans of an Astribank to T1. The
+#  Astribanks is specified by its location instead of hardware_id
+#@pci0000:00/0000:00:03.3/usb1/1-5/xbus-01/astribanks:xbus-01 [12]:T1