1#! /bin/sh
2#  make-udev-rules -- creates udev rules from hotplug match info
3#  Copyright (C) 2006, 2007  SEIKO EPSON Corporation
4
5#  This file is part of "Image Scan! for Linux".
6#  You can redistribute it and/or modify it under the terms of the GNU
7#  General Public License as published by the Free Software Foundation;
8#  either version 2 of the License or at your option any later version.
9#
10#  This program is distributed in the hope that it will be useful, but
11#  WITHOUT ANY WARRANTY;  without even the implied warranty of FITNESS
12#  FOR A PARTICULAR PURPOSE or MERCHANTABILITY.
13#  See the GNU General Public License for more details.
14#
15#  You should have received a verbatim copy of the GNU General Public
16#  License along with this program; if not, write to:
17#
18#      Free Software Foundation, Inc.
19#      59 Temple Place, Suite 330
20#      Boston, MA  02111-1307  USA
21
22
23USERMAP=${1}			# location of iscan.usermap
24RULEDIR=${2:-/etc/udev/rules.d}
25
26TEMPLATE='SYSFS{idVendor}=="04b8", SYSFS{idProduct}=="HHHH", MODE="0666"'
27SUB_SYST='usb_device'
28
29#  Convenience functions.
30
31usage () {
32    cat <<EOF
33Usage: make-udev-rules FILE [UDEV_RULES_DIR]
34Creates a udev rules file using the hotplug match information found
35in FILE.  The UDEV_RULES_DIR is searched for SANE related files for
36use in rule template generation.  It defaults to /etc/udev/rules.d.
37A rules file will be written to *iscan.rules in UDEV_RULES_DIR.
38
39Setting the DEBUG environment variable to a non-empty string can be
40used to divert the rules to standard output instead.
41EOF
42}
43
44debug () {
45    test x$DEBUG != x || return 0
46    echo DBG: $* >&2
47}
48
49get_usb_product_ids () {
50    sed 's/#.*//; /^[[:space:]]*$/d' $USERMAP \
51	| awk '{print $4}' \
52	| sed 's/0x//' \
53	| tr '\n' ' '
54}
55
56#  Although this function takes line continuation into account, it
57#  does assume that SYSFS{idVendor} is on the first line.
58#
59get_template_rule () {
60    sed -n 's/#.*//; /^[[:space:]]*$/d
61    /SYSFS{idVendor}=\{1,2\}"04[bB]8"/{
62    /\\$/N
63    s/\\\n//
64    p
65    q
66    }' $* \
67	| sed 's/\(SYSFS{idProduct}=\{1,2\}\)"[[:xdigit:]]\{4\}"/\1"HHHH"/'
68}
69
70#  Heavily based on get_template_rule (), this tries to find the name
71#  that is used by udev for the USB subsystem.  Unfortunately not all
72#  distributions (kernel/udev versions?) use the same name.
73#
74get_sub_syst_name () {
75    sed -n 's/#.*//; /^[[:space:]]*$/d
76    /SUBSYSTEM!\{,1\}=\{1,2\}"usb.*"/{
77    p
78    q
79    }' $* \
80	| sed 's/.*SUBSYSTEM!\{,1\}=\{1,2\}"\([^"]*\)".*/\1/'
81}
82
83#  WARNING: this heavily relies on the fact that we only try existing
84#  rules files that match lib*.rules.
85#
86get_out_file_name () {
87    ls $* | sed 's/lib[^.]*/iscan/'
88}
89
90#  Sanity tests.
91
92if test -z "$USERMAP"; then
93    usage
94    exit 1
95fi
96
97LC_ALL=C			# sanitise environment a bit
98RULEDIR=${RULEDIR%%/}
99
100prod_ids="`get_usb_product_ids`"
101test -n "$prod_ids" || exit 1
102
103template=
104out_file=
105for rules in \
106    libsane.rules \
107    libusbscanner.rules \
108    ; do
109    template="`get_template_rule $RULEDIR/*$rules 2>/dev/null`"
110    sub_syst="`get_sub_syst_name $RULEDIR/*$rules 2>/dev/null`"
111    out_file="`get_out_file_name $RULEDIR/*$rules 2>/dev/null`"
112    test -n "$template" && break
113done
114debug "Using template from $RULEDIR/*$rules"
115
116if test -z "$template"; then
117    template="$TEMPLATE"
118    out_file=$RULEDIR/60_iscan.rules
119fi
120if test -z "$sub_syst"; then
121    sub_syst="$SUB_SYST"
122fi
123
124if test x$DEBUG != x; then
125    debug "Would have sent output to $out_file"
126else				# better make sure
127    test -d $RULEDIR || mkdir -p $RULEDIR
128    exec 1> $out_file
129fi
130
131
132cat <<EOF
133# This file is part of the "Image Scan! for Linux" binary package (or
134# generated automatically as part of its installation).  Any changes
135# will be overwritten with each upgrade of the package.
136
137ACTION!="add", GOTO="iscan_rules_end"
138SUBSYSTEM!="$sub_syst", GOTO="iscan_rules_end"
139
140EOF
141
142for id in $prod_ids; do
143    echo $template | sed "s,HHHH,$id,"
144done
145
146cat <<EOF
147
148LABEL="iscan_rules_end"
149EOF
150
151exit 0
152