summaryrefslogtreecommitdiffstats
path: root/perl-install/scanner.pm
diff options
context:
space:
mode:
Diffstat (limited to 'perl-install/scanner.pm')
-rwxr-xr-xperl-install/scanner.pm606
1 files changed, 0 insertions, 606 deletions
diff --git a/perl-install/scanner.pm b/perl-install/scanner.pm
deleted file mode 100755
index 819ae84e2..000000000
--- a/perl-install/scanner.pm
+++ /dev/null
@@ -1,606 +0,0 @@
-package scanner;
-# scanner.pm $Id$
-# Yves Duret <yduret at mandrakesoft.com>
-# Till Kamppeter <till at mandrakesoft.com>
-# Copyright (C) 2001-2004 MandrakeSoft
-#
-# 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, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-#
-# pbs/TODO:
-# - scsi mis-configuration (should work better now)
-# - devfs use dev_is_devfs()
-# - with 2 scanners same manufacturer -> will overwrite previous conf -> only 1 conf !! (should work now)
-# - lp: see printerdrake
-# - install: prefix --> done (partially)
-
-use common;
-use detect_devices;
-use log;
-use handle_configs;
-
-my $sanedir = "$::prefix/etc/sane.d";
-my $scannerDBdir = "$::prefix$ENV{SHARE_PATH}/ldetect-lst";
-our $scannerDB = readScannerDB("$scannerDBdir/ScannerDB");
-
-sub confScanner {
- my ($model, $port, $vendor, $product, $firmware) = @_;
- $port ||= detect_devices::dev_is_devfs() ? "$::prefix/dev/usb/scanner0" : "$::prefix/dev/scanner";
- my $a = $scannerDB->{$model}{server};
- #print "file:[$a]\t[$model]\t[$port]\n| ", (join "\n| ", @{$scannerDB->{$model}{lines}}),"\n";
- 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")));
- 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;
- # Install firmware
- run_program::rooted($::prefix, "mkdir", "-p",
- "/usr/share/sane/firmware") || do {
- $in->ask_warn('Scannerdrake',
- 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") || do {
- $in->ask_warn('Scannerdrake',
- N("Could not create link /usr/share/sane/%s!", $backend));
- return "";
- };
- }
- run_program::rooted($::prefix, "cp", "-f", "$firmware",
- "/usr/share/sane/firmware") || do {
- $in->ask_warn('Scannerdrake',
- 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) || do {
- $in->ask_warn('Scannerdrake',
- N("Could not set permissions of firmware file %s!", $firmware));
- return "";
- };
- return $firmware;
-}
-
-sub configured() {
- my @res;
- my $parportscannerfound = 0;
- # Run "scanimage -L", to find the scanners which are already working
- local *LIST;
- open 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
- $port =~ /^([^:]+):/;
- my $backend = $1;
- # Does the scanner need a firmware file
- my $firmwareline = firmwareline($backend);
- # Store collected data
- push @res, {
- port => $port,
- val => {
- DESCRIPTION => $description,
- ($backend ? ( BACKEND => $backend ) : ()),
- ($firmwareline ?
- ( FIRMWARELINE => $firmwareline ) : ()),
- }
- }
- }
- }
- close LIST;
- # We have a parallel port scanner, make it working for non-root users
- nonroot_access_for_parport($parportscannerfound);
- return @res;
-}
-
-sub nonroot_access_for_parport {
-
- # This function configures a non-root access for parallel port
- # scanners by running saned as root, esporting 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) = @_;
- # Is saned running?
- my $sanedrunning = services::starts_on_boot("saned");
- # Is the "net" SANE backend active
- my $netbackendactive = grep { /^\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 and xinetd is installed and
- # running
- if (!files_exist('/usr/sbin/xinetd',
- '/usr/sbin/saned')) {
- if (!$in->do_pkgs->install('xinetd', '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;
- }
- }
-
- # Modify /etc/xinetd.d/saned to let saned run as root
- my @sanedxinetdconf = cat_("/etc/xinetd.d/saned");
- ( s/(user\s*=\s*).*$/$1root/ ) foreach @sanedxinetdconf;
- ( s/(group\s*=\s*).*$/$1root/ ) foreach @sanedxinetdconf;
- output("/etc/xinetd.d/saned", @sanedxinetdconf);
-
- # 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::start_service_on_boot("saned");
- services::start_service_on_boot("xinetd");
- services::restart("xinetd");
-
- } else {
- # Disable non-root access
-
- if (-r "/etc/xinetd.d/saned") {
- # Modify /etc/xinetd.d/saned to let saned run as saned
- my @sanedxinetdconf = cat_("/etc/xinetd.d/saned");
- ( s/(user\s*=\s*).*$/$1saned/ ) foreach @sanedxinetdconf;
- ( s/(group\s*=\s*).*$/$1saned/ ) foreach @sanedxinetdconf;
- output("/etc/xinetd.d/saned", @sanedxinetdconf);
- # Restart xinetd
- services::restart("xinetd") if $sanedrunning;
- }
- }
-
- return 1;
-}
-
-sub detect {
- my @configured = @_;
- my @res;
- # Run "sane-find-scanner", this also detects USB scanners which only
- # work with libusb.
- local *DETECT;
- open DETECT, "LC_ALL=C sane-find-scanner -q |";
- while (my $line = <DETECT>) {
- my ($vendorid, $productid, $make, $model, $description, $port);
- 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) {
- # We have vendor and product ID, look up the scanner in
- # the usbtable
- foreach my $entry (cat_("$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,
- }
- };
- }
- 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;
- }
- return @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`;
- 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) = @_;
- local *DETECT;
- if ($port =~ /^\s*libusb:(\d+):(\d+)\s*$/) {
- # Use "lsusb" to find the USB IDs
- open 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";
- last;
- }
- }
- } else {
- # Run "sane-find-scanner" on the port
- open 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) = @_;
- my ($card, %cards);
-
- my $F = common::openFileMaybeCompressed($file);
-
- my ($lineno, $cmd, $val) = 0;
- my $fs = {
- 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;
- $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} || []};
- add2hash($card->{flags}, $c->{flags});
- add2hash($card, $c);
- },
- ASK => sub { $card->{ask} = $val },
- SERVER => sub { $card->{server} = $val },
- DRIVER => sub { $card->{driver} = $val },
- UNSUPPORTED => sub { $card->{flags}{unsupported} = 1 },
- COMMENT => sub {},
- };
-
- local $_;
- while (<$F>) { $lineno++;
- s/\s+$//;
- /^#/ and next;
- /^$/ and next;
- /^END/ and do { $cards{$card->{type}} = $card if $card; last };
- ($cmd, $val) = /(\S+)\s*(.*)/ or next; #log::l("bad line $lineno ($_)"), next;
- my $f = $fs->{$cmd};
- $f ? $f->() : log::l("unknown line $lineno ($_)");
- }
- \%cards;
-}
-
-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 if $mod ne '"scanner"';
- $name =~ s/\"(.*)\"$/$1/;
- if (member($name, keys %$scanner::scannerDB)) {
- print "#[$name] already in ScannerDB!\n";
- next;
- }
- $to_add .= "NAME $name\nDRIVER USB\nCOMMENT usb $vendor_id $product_id\nUNSUPPORTED\n\n";
- }
- $to_add .= "END\n";
-
- append_to_file("ScannerDB", $to_add);
-}
-
-sub updateScannerDBfromSane {
- my ($sanesrcdir) = @_;
- substInFile { s/^END// } "ScannerDB";
-
- 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" => "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/ or $_[0] = "Hewlett-Packard|$_[0]"; $_[0] },
- "Kodak" => "Kodak Co.",
- "Mustek" => "Mustek Systems Inc.",
- "NEC" => "NEC Systems",
- "Nikon" => "Nikon Corp.",
- "Plustek" => "Plustek, Inc.",
- "Primax" => "Primax Electronics",
- "Siemens" => "Siemens Information and Communication Products",
- "Trust" => "Trust Technologies",
- "UMAX" => "Umax",
- "Vobis/Highscreen" => "Vobis",
- };
-
- # 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) = 0;
- 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; return }
- $name = member($mfg, keys %$sane2DB) ?
- 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 {
- # 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 = $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;
- },
- interface => sub { $intf = $val },
- comment => sub { $comment = $val },
- };
- local $_;
- while (<$F>) { $lineno++;
- s/\s+$//;
- /^;/ 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
- }
- $to_add .= "\nEND\n";
- append_to_file("ScannerDB", $to_add);
-}
-
-1; #