summaryrefslogtreecommitdiffstats
path: root/perl-install/scanner.pm
diff options
context:
space:
mode:
Diffstat (limited to 'perl-install/scanner.pm')
-rw-r--r--[-rwxr-xr-x]perl-install/scanner.pm562
1 files changed, 481 insertions, 81 deletions
diff --git a/perl-install/scanner.pm b/perl-install/scanner.pm
index f6351ca46..777f7192f 100755..100644
--- a/perl-install/scanner.pm
+++ b/perl-install/scanner.pm
@@ -1,7 +1,7 @@
package scanner;
-# scanner.pm $Id$
-# Yves Duret <yduret at mandrakesoft.com>
-# Copyright (C) 2001 MandrakeSoft
+# Yves Duret <yduret at mandriva.com>
+# Till Kamppeter <till at mandriva.com>
+# Copyright (C) 2001-2008 Mandriva
#
# 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
@@ -18,62 +18,421 @@ package scanner;
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
# pbs/TODO:
-# - scsi mis-configuration
-# - devfs use dev_is_devfs()
-# - with 2 scanners same manufacturer -> will overwrite previous conf -> only 1 conf !!
+# - scsi mis-configuration (should work better now)
+# - with 2 scanners same manufacturer -> will overwrite previous conf -> only 1 conf !! (should work now)
# - lp: see printerdrake
-# - install: prefix --> done
+# - install: prefix --> done (partially)
-use standalone;
use common;
use detect_devices;
+use log;
+use handle_configs;
-
-my $_sanedir = "$prefix/etc/sane.d";
-my $_scannerDBdir = "$prefix$ENV{SHARE_PATH}/ldetect-lst";
-$scannerDB = readScannerDB("$_scannerDBdir/ScannerDB");
+my $sanedir = "$::prefix/etc/sane.d";
+my $scannerDBdir = "$::prefix$ENV{SHARE_PATH}/ldetect-lst";
+our $scannerDB = readScannerDB("$scannerDBdir/ScannerDB");
sub confScanner {
- my ($model, $port) = @_;
- $port = detect_devices::dev_is_devfs() ? "$prefix/dev/usb/scanner0" : "$prefix/dev/scanner" if (!$port);
+ my ($model, $port, $vendor, $product, $firmware) = @_;
+ $port ||= "/dev/scanner";
my $a = $scannerDB->{$model}{server};
#print "file:[$a]\t[$model]\t[$port]\n| ", (join "\n| ", @{$scannerDB->{$model}{lines}}),"\n";
- output("$_sanedir/$a.conf", (join "\n",@{$scannerDB->{$model}{lines}}));
- substInFile { s/\$DEVICE/$port/ } "$_sanedir/$a.conf";
+ my @driverconf = cat_("$sanedir/$a.conf");
+ my @configlines = @{$scannerDB->{$model}{lines}};
+ foreach my $line (@configlines) {
+ $line =~ s/\$DEVICE/$port/g if $port;
+ next if $line =~ /\$DEVICE/;
+ $line =~ s/\$VENDOR/$vendor/g if $vendor;
+ next if $line =~ /\$VENDOR/;
+ $line =~ s/\$PRODUCT/$product/g if $product;
+ next if $line =~ /\$PRODUCT/;
+ $line =~ s/\$FIRMWARE/$firmware/g if $firmware;
+ next if $line =~ /\$FIRMWARE/;
+ my $linetype;
+ if ($line =~ /^(\S*)LINE\s+(.*?)$/) {
+ $linetype = $1;
+ $line = $2;
+ }
+ next if !$line;
+ if (!$linetype ||
+ ($linetype eq "USB" && ($port =~ /usb/i || $vendor)) ||
+ ($linetype eq "PARPORT" && !$vendor &&
+ $port =~ /(parport|pt_drv|parallel)/i) ||
+ ($linetype eq "SCSI" && !$vendor &&
+ $port =~ m!(/sg|scsi|/scanner)!i)) {
+ handle_configs::set_directive(\@driverconf, $line, 1);
+ } elsif ($linetype eq "FIRMWARE" && $firmware) {
+ handle_configs::set_directive(\@driverconf, $line, 0);
+ }
+ }
+ output("$sanedir/$a.conf", @driverconf);
add2dll($a);
}
sub add2dll {
- return if member($_[0], chomp_(cat_("$_sanedir/dll.conf")));
- local *F;
- open F, ">>$_sanedir/dll.conf" or die "can't write SANE config in $_sanedir/dll.conf: $!";
- print F $_[0];
- close F;
+ return if member($_[0], chomp_(cat_("$sanedir/dll.conf")));
+ my @dllconf = cat_("$sanedir/dll.conf");
+ handle_configs::add_directive(\@dllconf, $_[0]);
+ output("$sanedir/dll.conf", @dllconf);
+}
+
+sub setfirmware {
+ my ($backend, $firmwareline) = @_;
+ my @driverconf = cat_("$sanedir/$backend.conf");
+ handle_configs::set_directive(\@driverconf, $firmwareline, 0);
+ output("$sanedir/$backend.conf", @driverconf);
+}
+
+sub installfirmware {
+ # Install the firmware file in /usr/share/sane/firmware
+ my ($firmware, $backend) = @_;
+ return "" if !$firmware;
+ $in ||= interactive->vnew;
+ # Install firmware
+ run_program::rooted($::prefix, "mkdir", "-p",
+ "/usr/share/sane/firmware") or do {
+ $in->ask_warn(N("Error"),
+ N("Could not create directory /usr/share/sane/firmware!"));
+ return "";
+ };
+ # Link /usr/share/sane/firmware to /usr/share/sane/<backend name> as
+ # some backends ignore the supplied absolute path to the firmware file
+ # and always search their own directory
+ if ($backend) {
+ run_program::rooted($::prefix, "ln", "-sf",
+ "/usr/share/sane/firmware",
+ "/usr/share/sane/$backend") or do {
+ $in->ask_warn(N("Error"),
+ N("Could not create link /usr/share/sane/%s!", $backend));
+ return "";
+ };
+ }
+ run_program::rooted($::prefix, "cp", "-f", $firmware,
+ "/usr/share/sane/firmware") or do {
+ $in->ask_warn(N("Error"),
+ N("Could not copy firmware file %s to /usr/share/sane/firmware!", $firmware));
+ return "";
+ };
+ $firmware =~ s!^(.*)(/[^/]+)$!/usr/share/sane/firmware$2!;
+ run_program::rooted($::prefix, "chmod", "644",
+ $firmware) or do {
+ $in->ask_warn(N("Error"),
+ N("Could not set permissions of firmware file %s!", $firmware));
+ return "";
+ };
+ return $firmware;
+}
+
+sub configured {
+ my ($in) = @_;
+ my @res;
+ my $parportscannerfound = 0;
+ # Run "scanimage -L", to find the scanners which are already working
+ open my $LIST, "LC_ALL=C scanimage -L |";
+ while (my $line = <$LIST>) {
+ if ($line =~ /^\s*device\s*`([^`']+)'\s+is\s+a\s+(\S.*)$/) {
+ # Extract port and description
+ my $port = $1;
+ my $description = $2;
+ # Remove duplicate scanners appearing through saned and the
+ # "net" backend
+ next if $port =~ /^net:(localhost|127.0.0.1):/;
+ # Is the scanner hooked to a parallel or serial port?
+ if ($port =~ /(parport|pt_drv|parallel|ttys)/i) {
+ $parportscannerfound = 1;
+ }
+ # Determine which SANE backend the scanner in question uses
+ my $backend;
+ $backend = $1 if $port =~ /^([^:]+):/;
+ # Does the scanner need a firmware file
+ my $firmwareline = firmwareline($backend);
+ # Store collected data
+ push @res, {
+ port => $port,
+ val => {
+ DESCRIPTION => $description,
+ if_($backend, BACKEND => $backend),
+ if_($firmwareline,
+ FIRMWARELINE => $firmwareline),
+ }
+ };
+ }
+ }
+ close $LIST;
+ # We have a parallel port scanner, make it working for non-root users
+ nonroot_access_for_parport($parportscannerfound, $in);
+ return @res;
+}
+
+sub nonroot_access_for_parport {
+
+ # This function configures a non-root access for parallel port
+ # scanners by running saned as root, exporting the scanner to
+ # localhost and letting the user's frontend use the "net" backend
+ # to access the scanner through the loopback network device.
+
+ # See also
+ # http://www.linuxprinting.org/download/digitalimage/Scanning-as-Normal-User-on-Wierd-Scanner-Mini-HOWTO.txt
+
+ # Desired state of this facility: 1: Enable, 0: Disable
+ my ($enable, $in) = @_;
+ # Is saned running?
+ my $sanedrunning = services::starts_on_boot("saned.socket");
+ # Is the "net" SANE backend active
+ my $netbackendactive = find { /^\s*net\s*$/ }
+ cat_("/etc/sane.d/dll.conf");
+ # Set this to 1 to tell the caller that the list of locally available
+ # scanners has changed (Here if the SANE client configuration has
+ # changed)
+ my $changed = 0;
+ my $importschanged = 0;
+ if ($enable) {
+ # Enable non-root access
+
+ # Install/start saned
+ if (!$sanedrunning) {
+ # Make sure saned is installed and running
+ if (!files_exist('/usr/sbin/saned')) {
+ if (!$in->do_pkgs->install('saned')) {
+ $in->ask_warn(N("Scannerdrake"),
+ N("Could not install the packages needed to share your scanner(s).") . " " .
+ N("Your scanner(s) will not be available for non-root users."));
+ }
+ return 0;
+ }
+ }
+
+ # Read list of hosts to where to export the local scanners
+ my @exports = cat_("/etc/sane.d/saned.conf");
+ # Read list of hosts from where to import scanners
+ my @imports = cat_("/etc/sane.d/net.conf");
+ # Add "localhost" to the machines which saned exports
+ handle_configs::set_directive(\@exports, "localhost")
+ if !member("localhost\n", @exports);
+ # Add "localhost" to the machines which "net" imports
+ handle_configs::set_directive(\@imports, "localhost")
+ if !member("localhost\n", @imports);
+ # Write /etc/sane.d/saned.conf
+ output("/etc/sane.d/saned.conf", @exports);
+ # Write /etc/sane.d/net.conf
+ output("/etc/sane.d/net.conf", @imports);
+
+ # Make sure that the "net" backend is active
+ scanner::add2dll("net");
+
+ # (Re)start saned and make sure that it gets started on
+ # every boot
+ services::enable("saned.socket");
+ }
+
+ return 1;
}
sub detect {
- my ($i, $elem, @res) = (0, {});
- foreach (grep { $_->{driver} =~ /scanner/ } detect_devices::usb_probe()) {
- #my ($manufacturer, $model) = split '\|', $_->{description};
- #$_->{description} =~ s/Hewlett[-\s_]Packard/HP/;
- push @res, { port => "/dev/usb/scanner$i", val => { #CLASS => 'SCANNER',
- #MODEL => $model,
- #MANUFACTURER => $manufacturer,
- DESCRIPTION => $_->{description},
- #id => $_->{id},
- #vendor => $_->{vendor},
- }};
- ++$i;
+ my @configured = @_;
+ my @res;
+ # Run "sane-find-scanner", this also detects USB scanners which only
+ # work with libusb.
+
+ my @devices = detect_devices::probeall();
+
+ open my $DETECT, "LC_ALL=C sane-find-scanner -q |";
+ while (my $line = <$DETECT>) {
+ my ($vendorid, $productid, $make, $model, $description, $port, $driver);
+ my $real_device;
+ if ($line =~ /^\s*found\s+USB\s+scanner/i) {
+ # Found an USB scanner
+ if ($line =~ /vendor=(0x[0-9a-f]+)[^0-9a-f\[]+[^\[]*\[([^\[\]]+)\].*prod(|uct)=(0x[0-9a-f]+)[^0-9a-f\[]+[^\[]*\[([^\[\]]+)\]/) {
+ # Scanner connected via libusb
+ $vendorid = $1;
+ $make = $2;
+ $productid = $4;
+ $model = $5;
+ $description = "$make|$model";
+ } elsif ($line =~ /vendor=(0x[0-9a-f]+)[^0-9a-f]+.*prod(|uct)=(0x[0-9a-f]+)[^0-9a-f]+/) {
+ # Scanner connected via scanner.o kernel module
+ $vendorid = $1;
+ $productid = $3;
+ }
+ if ($vendorid && $productid) {
+ my ($vendor) = $vendorid =~ /0x([0-9a-f]+)/;
+ my ($id) = $productid =~ /0x([0-9a-f]+)/;
+ my ($device) = grep { sprintf("%04x", $_->{vendor}) eq $vendor && sprintf("%04x", $_->{id}) eq $id } @devices;
+
+ if ($device) {
+ $driver = $device->{driver};
+ $real_device = $device;
+ } else {
+ #warn "Failed to lookup $vendorid and $productid!\n";
+ }
+
+ # We have vendor and product ID, look up the scanner in
+ # the usbtable
+ foreach my $entry (common::catMaybeCompressed("$scannerDBdir/usbtable")) {
+ if ($entry =~
+ /^\s*$vendorid\s+$productid\s+.*"([^"]+)"\s*$/) {
+ $description = $1;
+ $description =~ s/Seiko\s+Epson/Epson/i;
+ if ($description =~ /^([^\|]+)\|(.*)$/) {
+ $make = $1;
+ $model = $2;
+ }
+ last;
+ }
+ }
+ }
+ } elsif ($line =~ /^\s*found\s+SCSI/i) {
+ # SCSI scanner
+ if ($line =~ /"([^"\s]+)\s+([^"]+?)\s+([^"\s]+)"/) {
+ $make = $1;
+ $model = $2;
+ $description = "$make|$model";
+ }
+ } else {
+ # Comment line in output of "sane-find-scanner"
+ next;
+ }
+ # The Alcatel Speed Touch internet scanner is not supported by
+ # SANE
+ next if $description =~ /Alcatel.*Speed.*Touch|Camera|ISDN|ADSL/i;
+ # Extract port
+ $port = $1 if $line =~ /\s+(\S+)\s*$/;
+ # Check for duplicate (scanner.o/libusb)
+ if ($port =~ /^libusb/) {
+ my $duplicate = 0;
+ foreach (@res) {
+ if ($_->{val}{vendor} eq $vendorid &&
+ $_->{val}{id} eq $productid &&
+ $_->{port} =~ /dev.*usb.*scanner/ &&
+ !defined($_->{port2})) {
+ # Duplicate entry found, merge the entries
+ $_->{port2} = $port;
+ $_->{val}{MANUFACTURER} ||= $make;
+ $_->{val}{MODEL} ||= $model;
+ $_->{val}{DESCRIPTION} ||= $description;
+ $duplicate = 1;
+ last;
+ }
+ }
+ next if $duplicate;
+ }
+ # Store collected data
+ push @res, {
+ port => $port,
+ val => {
+ CLASS => 'SCANNER',
+ MODEL => $model,
+ MANUFACTURER => $make,
+ DESCRIPTION => $description,
+ id => $productid,
+ vendor => $vendorid,
+ driver => $driver,
+ drakx_device => $real_device,
+ }
+ };
}
- foreach (grep { $_->{media_type} =~ /scanner/ } detect_devices::getSCSI()) {
- push @res, { port => "/dev/sg",
- val => { DESCRIPTION => $_->{info} },
- };
- ++$i;
+ close $DETECT;
+ if (@configured) {
+ # Remove scanners which are already working
+ foreach my $d (@res) {
+ my $searchport1 =
+ handle_configs::searchstr(resolve_symlinks($d->{port}));
+ my $searchport2 =
+ handle_configs::searchstr(resolve_symlinks($d->{port2}));
+ foreach my $c (@configured) {
+ my $currentport = resolve_symlinks($c->{port});
+ if ($currentport =~ /$searchport1$/ ||
+ $searchport2 && $currentport =~ /$searchport2$/) {
+ $d->{configured} = 1;
+ last;
+ }
+ }
+ }
+ @res = grep { ! $_->{configured} } @res;
}
- @res;
+ # blacklist device that have a driver b/c of buggy sane-find-scanner:
+ return grep { member($_->{val}{driver}, qw(scanner unknown usbcore)) } @res;
}
+sub resolve_symlinks {
+
+ # Check if a given file (either the pure filename or in a SANE device
+ # string as "<prefix>:<file>") is a symlink, if so expand the link.
+ # If the new file name is a link, expand again, until finding the
+ # physical file.
+ my ($file) = @_;
+ my $prefix = "";
+ if ($file =~ m!^([^/]*)(/.*)$!) {
+ $prefix = $1;
+ $file = $2;
+ } else {
+ return $file;
+ }
+ while (1) {
+ my $ls = `ls -l $file 2> /dev/null`;
+ if ($ls =~ m!\s($file)\s*\->\s*(\S+)\s*$!) {
+ my $target = $2;
+ if ($target !~ m!^/! && $file =~ m!^(.*)/[^/]+$!) {
+ $target = "$1/$target";
+ }
+ $file = $target;
+ } else {
+ last;
+ }
+ }
+ return $prefix . $file;
+}
+
+sub get_usb_ids_for_port {
+ my ($port) = @_;
+ if ($port =~ /^\s*libusb:(\d+):(\d+)\s*$/) {
+ # Use "lsusb" to find the USB IDs
+ open my $DETECT, "LC_ALL=C lsusb -s $1:$2 |";
+ while (my $line = <$DETECT>) {
+ if ($line =~ /ID\s+([0-9a-f]+):(0x[0-9a-f]+)($|\s+)/) {
+ # Scanner connected via scanner.o kernel module
+ return "0x$1", "0x$2";
+ }
+ }
+ } else {
+ # Run "sane-find-scanner" on the port
+ open my $DETECT, "LC_ALL=C sane-find-scanner -q $port |";
+ while (my $line = <$DETECT>) {
+ if ($line =~ /^\s*found\s+USB\s+scanner/i) {
+ if ($line =~ /vendor=(0x[0-9a-f]+)[^0-9a-f]+.*prod(|uct)=(0x[0-9a-f]+)[^0-9a-f]+/) {
+ # Scanner connected via scanner.o kernel module
+ return $1, $3;
+ }
+ }
+ }
+ }
+}
+
+sub readconfiglinetemplates {
+ # Read templates for configuration file lines
+ my %configlines;
+ my $backend;
+ foreach my $line (cat_("$scannerDBdir/scannerconfigs")) {
+ chomp $line;
+ if ($line =~ /^\s*SERVER\s+(\S+)\s*$/) {
+ $backend = $1;
+ } elsif ($backend) {
+ push @{$configlines{$backend}}, $line;
+ }
+ }
+ return \%configlines;
+}
+
+sub firmwareline {
+ # Determine whether the given SANE backend supports a firmware file
+ # and return the line needed in the config file
+ my ($backend) = @_;
+ # Read templates for configuration file lines
+ my %configlines = %{readconfiglinetemplates()};
+ # Does the backend support a line for the firmware?
+ my @firmwarelines = (grep { s/^FIRMWARELINE // } @{$configlines{$backend}});
+ return join("\n", @firmwarelines);
+}
sub readScannerDB {
my ($file) = @_;
@@ -81,14 +440,22 @@ sub readScannerDB {
my $F = common::openFileMaybeCompressed($file);
- my ($lineno, $cmd, $val) = 0;
+ my ($cmd, $val);
+ my $lineno = 0;
my $fs = {
- LINE => sub { push @{$card->{lines}}, $val },
+ LINE => sub { push @{$card->{lines}}, "LINE $val" },
+ SCSILINE => sub { push @{$card->{lines}}, "SCSILINE $val" },
+ USBLINE => sub { push @{$card->{lines}}, "USBLINE $val" },
+ PARPORTLINE => sub { push @{$card->{lines}}, "PARPORTLINE $val" },
+ FIRMWARELINE => sub { push @{$card->{lines}}, "FIRMWARELINE $val" },
NAME => sub {
- $cards{$card->{type}} = $card if ($card and !$card->{flags}{unsupported});
+ #$cards{$card->{type}} = $card if ($card and !$card->{flags}{unsupported});
+ $cards{$card->{type}} = $card if $card;
+ $val =~ s/Seiko\s+Epson/Epson/i;
$card = { type => $val };
},
SEE => sub {
+ $val =~ s/Seiko\s+Epson/Epson/i;
my $c = $cards{$val} or die "Error in database, invalid reference $val at line $lineno";
push @{$card->{lines}}, @{$c->{lines} || []};
@@ -98,7 +465,13 @@ sub readScannerDB {
ASK => sub { $card->{ask} = $val },
SERVER => sub { $card->{server} = $val },
DRIVER => sub { $card->{driver} = $val },
+ KERNEL => sub { push(@{$card->{kernel}}, $val) },
+ SCSIKERNEL => sub { push(@{$card->{scsikernel}}, $val) },
+ USBKERNEL => sub { push(@{$card->{usbkernel}}, $val) },
+ PARPORTKERNEL => sub { push(@{$card->{parportkernel}}, $val) },
UNSUPPORTED => sub { $card->{flags}{unsupported} = 1 },
+ MANUAL => sub { $card->{flags}{manual} = 1 },
+ MANUALREQUIRED => sub { $card->{flags}{manual} = 2 },
COMMENT => sub {},
};
@@ -115,41 +488,39 @@ sub readScannerDB {
\%cards;
}
-sub updateScannerDBfromUsbtable {
- substInFile { s/END// } "ScannerDB";
- local *F;
- open F, ">>ScannerDB" or die "can't write ScannerDB config in ScannerDB: $!";
- print F "# generated from usbtable by scannerdrake\n";
+sub updateScannerDBfromUsbtable() {
+ substInFile { s/^END// } "ScannerDB";
+ my $to_add = "# generated from usbtable by scannerdrake\n";
foreach (cat_("$ENV{SHARE_PATH}/ldetect-lst/usbtable")) {
my ($vendor_id, $product_id, $mod, $name) = chomp_(split /\s/,$_,4);
- next unless ($mod eq "\"scanner\"");
- $name =~ s/\"(.*)\"$/$1/;
- if (member($name, keys %$scanner::scannerDB)) {
+ next if $mod ne '"scanner"';
+ $name =~ s/"(.*)"$/$1/;
+ if ($scanner::scannerDB->{$name}) {
print "#[$name] already in ScannerDB!\n";
next;
}
- print F "NAME $name\nDRIVER usb\nCOMMENT usb $vendor_id $product_id\nUNSUPPORTED\n\n";
+ $to_add .= "NAME $name\nDRIVER USB\nCOMMENT usb $vendor_id $product_id\nUNSUPPORTED\n\n";
}
- print F "END\n";
- close F;
+ $to_add .= "END\n";
+
+ append_to_file("ScannerDB", $to_add);
}
sub updateScannerDBfromSane {
- my ($_sanesrcdir) = @_;
- substInFile { s/END// } "ScannerDB";
+ my ($sanesrcdir) = @_;
+ substInFile { s/^END// } "ScannerDB";
- local *Y;
- open Y, ">>ScannerDB" or die "can't write ScannerDB config in ScannerDB: $!";
- print Y "# generated from Sane by scannerdrake\n";
+ my $to_add = "# generated from Sane by scannerdrake\n";
# for compat with our usbtable
my $sane2DB = {
"Acer" => "Acer Peripherals Inc.",
"AGFA" => "AGFA-Gevaert NV",
"Agfa" => "AGFA-Gevaert NV",
- "Epson" => "Seiko Epson Corp.",
+ "Epson" => "Epson Corp.",
"Fujitsu Computer Products of America" => "Fujitsu",
"HP" => sub { $_[0] =~ s/HP\s/Hewlett-Packard|/; $_[0] =~ s/HP4200/Hewlett-Packard|ScanJet 4200C/; $_[0] },
- "Hewlett-Packard" => sub { $_[0] =~ s/HP 3200 C/Hewlett-Packard|ScanJet 3200C/; $_[0] },
+ "Hewlett-Packard" => sub { $_[0] =~ s/HP 3200 C/Hewlett-Packard|ScanJet 3200C/ or $_[0] = "Hewlett-Packard|$_[0]"; $_[0] },
+ "Hewlett Packard" => "Hewlett-Packard",
"Kodak" => "Kodak Co.",
"Mustek" => "Mustek Systems Inc.",
"NEC" => "NEC Systems",
@@ -161,27 +532,56 @@ sub updateScannerDBfromSane {
"UMAX" => "Umax",
"Vobis/Highscreen" => "Vobis",
};
-
- opendir YREP, $_sanesrcdir or die "can't open $_sanesrcdir: $!";
- @files = grep /.*desc$/, readdir YREP;
- closedir YREP;
- foreach $i (@files) {
- my $F = common::openFileMaybeCompressed("$_sanesrcdir/$i");
- print Y "\n# from $i";
- my ($lineno, $cmd, $val) = 0;
- my ($name, $intf, $comment,$mfg);
+
+ # Read templates for configuration file lines
+ my %configlines = %{readconfiglinetemplates()};
+
+ foreach my $ff (glob_("$sanesrcdir/doc/descriptions/*.desc"), glob_("$sanesrcdir/doc/descriptions-external/*.desc"), "UNSUPPORTED") {
+ my $f = $ff;
+ # unsupported.desc must be treated separately, as the list of
+ # unsupported scanners in SANE is out of date.
+ next if $f =~ /unsupported.desc$/;
+ # Treat unsupported.desc in the end
+ $f = "$sanesrcdir/doc/descriptions/unsupported.desc" if
+ $f eq "UNSUPPORTED";
+ my $F = common::openFileMaybeCompressed($f);
+ $to_add .= "\n# from $f";
+ my ($lineno, $cmd, $val);
+ my ($name, $intf, $comment, $mfg, $backend);
my $fs = {
backend => sub { $backend = $val },
mfg => sub { $mfg = $val; $name = undef },#bug when a new mfg comes. should called $fs->{ $name }(); but ??
model => sub {
- unless ($name) { $name = $val; next }
- $name = (member($mfg, keys %$sane2DB))
- ? (ref $sane2DB->{ $mfg }) ? $sane2DB->{ $mfg }($name) : "$sane2DB->{ $mfg }|$name" : "$mfg|$name";
- if (member($name, keys %$scanner::scannerDB)) {
- print "#[$name] already in ScannerDB!\n";
+ unless ($name) { $name = $val; return }
+ $name = exists $sane2DB->{$mfg} ?
+ ref($sane2DB->{$mfg}) ? $sane2DB->{$mfg}($name) : "$sane2DB->{ $mfg }|$name" : "$mfg|$name";
+ # When adding the unsupported scanner models, check
+ # whether the model is not already supported. To
+ # compare the names ignore upper/lower case.
+ my $searchname = quotemeta($name);
+ if ($backend =~ /unsupported/i &&
+ $to_add =~ /^NAME $searchname$/im) {
+ $to_add .= "# $name already supported!\n";
} else {
- print Y "\nNAME $name\nSERVER $backend\nDRIVER $intf\n";
- print Y "COMMENT $comment\n" if ($comment);
+ # SANE bug: "snapscan" calls itself "SnapScan"
+ $backend =~ s/SnapScan/snapscan/g;
+ $to_add .= "\nNAME $name\nSERVER $backend\nDRIVER $intf\n";
+ # Go through the configuration lines of
+ # this backend and add what is needed for the
+ # interfaces of this scanner
+ foreach my $line (@{$configlines{$backend}}) {
+ my $i;
+ $i = $1 if $line =~ /^\s*(\S*?)LINE/;
+ if (!$i || $i eq "FIRMWARE" ||
+ $intf =~ /$i/i) {
+ $to_add .= "$line\n";
+ }
+ }
+ if ($backend =~
+ /(unsupported|mustek_pp|gphoto2)/i) {
+ $to_add .= "UNSUPPORTED\n";
+ }
+ $to_add .= "COMMENT $comment\n" if $comment;
$comment = undef;
}
$name = $val;
@@ -192,15 +592,15 @@ sub updateScannerDBfromSane {
local $_;
while (<$F>) { $lineno++;
s/\s+$//;
- /^\;/ and next;
- ($cmd, $val) = /:(\S+)\s*\"([^\;]*)\"/ or next; #log::l("bad line $lineno ($_)"), next;
- my $f = $fs->{ $cmd };
+ /^;/ and next;
+ ($cmd, $val) = /:(\S+)\s*"([^;]*)"/ or next; #log::l("bad line $lineno ($_)"), next;
+ my $f = $fs->{$cmd};
$f ? $f->() : log::l("unknown line $lineno ($_)");
}
$fs->{model}(); # the last one
}
- print Y "\nEND\n";
- close Y;
+ $to_add .= "\nEND\n";
+ append_to_file("ScannerDB", $to_add);
}
1; #