<html><head><meta name="color-scheme" content="light dark"></head><body><pre style="word-wrap: break-word; white-space: pre-wrap;">package detect_devices; # $Id: detect_devices.pm,v 1.148 2001/11/23 13:18:07 gc Exp $







use log;
use common;
use devices;
use c;




my @netdevices = map { my $l = $_; map { "$l$_" } (0..3) } qw(eth tr fddi plip);
my %serialprobe = ();




sub get {
    
    
    
    
    
    

    getIDE(), getSCSI(), getDAC960(), getCompaqSmartArray(), getATARAID();
}
sub hds() { grep { $_-&gt;{media_type} eq 'hd' &amp;&amp; ($::isStandalone || !isRemovableDrive($_)) } get(); }
sub zips() { grep { $_-&gt;{media_type} =~ /.d/ &amp;&amp; isZipDrive($_) } get(); }
sub ide_zips() { grep { $_-&gt;{media_type} =~ /.d/ &amp;&amp; isZipDrive($_) } getIDE(); }

sub ls120s() { grep { $_-&gt;{media_type} =~ /.d/ &amp;&amp; isLS120Drive($_) } get(); }
sub cdroms() { 
    my @l = grep { $_-&gt;{media_type} eq 'cdrom' } get(); 
    if (my @l2 = IDEburners()) {
	require modules;
	modules::add_alias('scsi_hostadapter', 'ide-scsi');
	my $nb = 1 + max(-1, map { $_-&gt;{device} =~ /scd(\d+)/ } @l);
	foreach my $i (@l2) {	    
	    log::l("IDEBurner: $i-&gt;{device}");
	    my ($e) = grep { $_-&gt;{device} eq $i-&gt;{device} } @l;
	    $e-&gt;{device} = "scd" . $nb++;
	}
    }
    @l;
}
sub burners    { grep { $_-&gt;{media_type} eq 'cdrom' &amp;&amp; isBurner($_) } get() }
sub IDEburners { grep { $_-&gt;{media_type} eq 'cdrom' &amp;&amp; isBurner($_) } getIDE() }
sub dvdroms    { grep { $_-&gt;{media_type} eq 'cdrom' &amp;&amp; isDvdDrive($_) } get() }

sub get_mac_model() {
    my $mac_model = cat_("/proc/device-tree/model") || die "Can't open /proc/device-tree/model";
    log::l("Mac model: $mac_model");
    $mac_model;	
}

sub get_mac_generation() {
    my $generation = cat_("/proc/cpuinfo") || die "Can't open /proc/cpuinfo";
    my @genarray = split(/\n/, $generation);
    my $count = 0;
    while ($count &lt;= @genarray) {
	if ($genarray[$count] =~ /pmac-generation/) {
	    @genarray = split(/:/, $genarray[$count]);
	    return $genarray[1];
	}
	$count++;
    }
    return "Unknown Generation";	
}

sub dev_is_devfs { -e "/dev/.devfsd" }

sub floppies() {
    require modules;
    eval { modules::load("floppy") };
    my @fds = map {
	my $info = (!dev_is_devfs() || -e "/dev/$_") &amp;&amp; c::floppy_info(devices::make($_));
	if_($info &amp;&amp; $info ne '(null)', { device =&gt; $_, media_type =&gt; 'fd', info =&gt; $info })
    } qw(fd0 fd1);
    my @ide = ls120s() and eval { modules::load("ide-floppy") };

    eval { modules::load("usb-storage") } if usbStorage();
    my @scsi = grep { $_-&gt;{media_type} eq 'fd' } getSCSI();
    @ide, @scsi, @fds;
}
sub floppies_dev() { map { $_-&gt;{device} } floppies() }
sub floppy { first(floppies_dev()) }


sub isBurner { 
    my $dev = $_[0]{device};
    if (my($nb) = $dev =~ /scd(.*)/) {
	grep { /^(scd|sr)$nb:.*writer/ } syslog();
    } else {
	my $f = tryOpen($dev); 
	$f &amp;&amp; c::isBurner(fileno($f));
    }
}
sub isDvdDrive {
    $_[0]{info} =~ /DVD/; 
    my $f = tryOpen($_[0]{device});
    $f &amp;&amp; c::isDvdDrive(fileno($f));
}
sub isZipDrive { $_[0]-&gt;{info} =~ /ZIP\s+\d+/ } 

sub isLS120Drive { $_[0]-&gt;{info} =~ /LS-?120|144MB/ }
sub isRemovableDrive { &amp;isZipDrive || &amp;isLS120Drive || $_[0]-&gt;{media_type} eq 'fd' } 

sub isFloppyOrHD {
    my ($dev) = @_;
    require partition_table_raw;
    my $geom = partition_table_raw::get_geometry(devices::make($dev));
    $geom-&gt;{totalsectors} &lt; 10 &lt;&lt; 11 ? 'fd' : 'hd';
}

sub getSCSI() {
    my @drives;
    my ($driveNum, $cdromNum, $tapeNum) = qw(0 0 0);
    my $err = sub { chop; die "unexpected line in /proc/scsi/scsi: $_"; };
    local $_;

    local *F;
    open F, "/proc/scsi/scsi" or return;
    local $_ = &lt;F&gt;; /^Attached devices:/ or return &amp;$err();
    while ($_ = &lt;F&gt;) {
	my ($id) = /^Host:.*?Id: (\d+)/ or return &amp;$err();
	$_ = &lt;F&gt;; my ($vendor, $model) = /^\s*Vendor:\s*(.*?)\s+Model:\s*(.*?)\s+Rev:/ or return &amp;$err();
	$_ = &lt;F&gt;; my ($type) = /^\s*Type:\s*(.*)/ or &amp;$err();
	my $device;
	if ($type =~ /Direct-Access/) { 
	    $device = "sd" . chr($driveNum++ + ord('a'));
	    $type = isFloppyOrHD($device);
	} elsif ($type =~ /Sequential-Access/) {
	    $device = "st" . $tapeNum++;
	    $type = 'tape';
	} elsif ($type =~ /CD-ROM/) {
	    $device = "scd" . $cdromNum++;
	    $type = 'cdrom';
	}
	$device and push @drives, { device =&gt; $device, media_type =&gt; $type, info =&gt; "$vendor $model", id =&gt; $id, bus =&gt; 0 };
    }
    @drives;
}

sub getIDE() {
    my @idi;

    
    -e "/proc/ide" or return ();

    
    foreach my $d (sort @{[glob_('/proc/ide/hd*')]}) {
	cat_("$d/driver") =~ /ide-scsi/ and next; 
	my $t = chomp_(cat_("$d/media"));
	my $type = $ {{disk =&gt; 'hd', cdrom =&gt; 'cdrom', tape =&gt; 'tape', floppy =&gt; 'fd'}}{$t} or next;
	my $info = chomp_(cat_("$d/model")) || "(none)";

	my $num = ord (($d =~ /(.)$/)[0]) - ord 'a';
	push @idi, { media_type =&gt; $type, device =&gt; basename($d), info =&gt; $info, bus =&gt; $num/2, id =&gt; $num%2 };
    }
    @idi;
}

sub getCompaqSmartArray() {
    my (@idi, $f);

    foreach ('array/ida', 'cpqarray/ida', 'cciss/cciss') {
	my $prefix = "/proc/driver/$_"; 
	$prefix = "/proc/$_" if !-e "${prefix}0"; 

	my ($name) = m|/(.*)|;
	for (my $i = 0; -r ($f = "${prefix}$i"); $i++) {
	    foreach (cat_($f)) {
		if (m|^\s*($name/.*?):|) {
		    push @idi, { device =&gt; $1, info =&gt; "Compaq RAID logical disk", media_type =&gt; 'hd' };
		}
	    }
	}
    }
    @idi;
}

sub getDAC960() {
    my %idi;

    
    
    foreach (syslog()) {
	my ($device, $info) = m|/dev/(rd/.*?): (.*?),| or next;
	$idi{$device} = { info =&gt; $info, media_type =&gt; 'hd', device =&gt; $device };
    }
    values %idi;
}

sub getATARAID {
    my %l;
    foreach (syslog()) {
	my ($device) = m|^\s*(ataraid/d\d+):| or next;
	$l{$device} = { info =&gt; 'ATARAID block device', media_type =&gt; 'hd', device =&gt; $device };
	log::l("ATARAID: $device");
    }
    values %l;
}

sub getNet() {
#      my @a;
#      foreach (@netdevices) {
#  	$::isStandalone &amp;&amp; /plip/ and next;
#  	print (" hhhhh $_ \n");
#  	/ippp/ and run_program::rooted("", "/sbin/isdnctrl addif $_");
#  	c::hasNetDevice($_) and push @a, $_;
#      }
#      /ippp/ and run_program::rooted("", "/sbin/isdnctrl delif $_") foreach @netdevices;
#      @a;
    grep { !(($::isStandalone || $::live) &amp;&amp; /plip/) &amp;&amp; c::hasNetDevice($_) } @netdevices;
}

#sub getISDN() {
#    mapgrep(sub {member (($_[0] =~ /\s*(\w*):/), @netdevices), $1 }, split(/\n/, cat_("/proc/net/dev")));
#}

sub pci_probe {
    my ($probe_type) = @_;
    log::l("full pci_probe") if $probe_type;
    map {
	my %l;
	@l{qw(vendor id subvendor subid pci_bus pci_device pci_function media_type driver description)} = split "\t";
	$l{$_} = hex $l{$_} foreach qw(vendor id subvendor subid);
	$l{bus} = 'PCI';
	\%l
    } c::pci_probe($probe_type || 0);
}

sub usb_probe {
    -e "/proc/bus/usb/devices" or return ();

    map {
	my %l;
	@l{qw(vendor id media_type driver description)} = split "\t";
	$l{$_} = hex $l{$_} foreach qw(vendor id);
	$l{bus} = 'USB';
	\%l
    } c::usb_probe();
}

sub pcmcia_probe {
    -e '/var/run/stab' || -e '/var/lib/pcmcia/stab' or return ();

    my (@devs, $desc);
    foreach (cat_('/var/run/stab'), cat_('/var/lib/pcmcia/stab')) {
	if (/^Socket\s+\d+:\s+(.*)/) {
	    $desc = $1;
	} else {
	    my (undef, $type, $module, undef, $device) = split;
	    push @devs, { description =&gt; $desc, driver =&gt; $module, type =&gt; $type, device =&gt; $device };
	}
    }
    @devs;
}

# pci_probe with $probe_type is unsafe for pci! (bug in kernel&amp;hardware)
# pcmcia_probe provides field "device", used in network.pm
# =&gt; probeall with $probe_type is unsafe
sub probeall {
    my ($probe_type) = @_;
    require sbus_probing::main;
    pci_probe($probe_type), usb_probe(), pcmcia_probe(), sbus_probing::main::probe();
}
sub matching_desc {
    my ($regexp) = @_;
    grep { $_-&gt;{description} =~ /$regexp/i } probeall();
}
sub stringlist { 
    map {
	sprintf("%-16s: %s%s%s", 
		$_-&gt;{driver} ? $_-&gt;{driver} : 'unknown', 
		$_-&gt;{description} eq '(null)' ? sprintf("Vendor=0x%04x Device=0x%04x", $_-&gt;{vendor}, $_-&gt;{id}) : $_-&gt;{description},
		$_-&gt;{media_type} ? sprintf(" [%s]", $_-&gt;{media_type}) : '',
		$_-&gt;{subid} &amp;&amp; $_-&gt;{subid} != 0xffff ? sprintf(" SubVendor=0x%04x SubDevice=0x%04x", $_-&gt;{subvendor}, $_-&gt;{subid}) : '',
	       );
    } probeall(@_); 
}
sub check {
    my ($l) = @_;
    my $ok = $l-&gt;{driver} !~ /(unknown|ignore)/;
    $ok or log::l("skipping $l-&gt;{description}, no module available (if you know one, please mail install\@mandrakesoft.com)");
    $ok
}


sub tryOpen($) {
    local *F;
    sysopen F, devices::make($_[0]), c::O_NONBLOCK() and *F;
}

sub tryWrite($) {
    local *F;
    sysopen F, devices::make($_[0]), 1 | c::O_NONBLOCK() and *F;
}

sub syslog {
    -r "/tmp/syslog" and return map { /&lt;\d+&gt;(.*)/ } cat_("/tmp/syslog");
    `$ENV{LD_LOADER} /bin/dmesg`;
}

sub hasSMP { c::detectSMP() }
sub hasPCMCIA { $::o-&gt;{pcmcia} } 



sub isLaptop {
    hasPCMCIA() || (matching_desc('C&amp;T.*655[45]\d') || matching_desc('C&amp;T.*68554') ||
		    matching_desc('Neomagic.*Magic(Media|Graph)') ||
		    matching_desc('ViRGE.MX') || matching_desc('S3.*Savage.*[IM]X') ||
		    matching_desc('ATI.*(Mobility|LT)'));
}

sub hasUltra66 {
    die "hasUltra66 deprecated";
    
    cat_("/proc/cmdline") =~ /(ide2=(\S+)(\s+ide3=(\S+))?)/ and return $1;

    my @l = map { $_-&gt;{verbatim} } matching_desc('HPT|Ultra66') or return;
    
    my $ide = sprintf "ide2=0x%x,0x%x ide3=0x%x,0x%x",
      @l == 2 ?
	(map_index { hex($_) + (odd($::i) ? 1 : -1) } map { (split ' ')[3..4] } @l) :
	(map_index { hex($_) + (odd($::i) ? 1 : -1) } map { (split ' ')[3..6] } @l);

    log::l("HPT|Ultra66: found $ide");
    $ide;
}

sub whatParport() {
    my @res = ();
    foreach (0..3) {
	my $elem = {};
	local *F;
	open F, "/proc/parport/$_/autoprobe" or open F, "/proc/sys/dev/parport/parport$_/autoprobe" or next;
	{
	    local $_;
	    while (&lt;F&gt;) { $elem-&gt;{$1} = $2 if /(.*):(.*);/ }
	}
	push @res, { port =&gt; "/dev/lp$_", val =&gt; $elem};
    }
    @res;
}

sub usbMice      { grep { $_-&gt;{media_type} =~ /\|Mouse/ &amp;&amp; $_-&gt;{driver} !~ /Tablet:wacom/} usb_probe() }
sub usbWacom     { grep { $_-&gt;{driver} =~ /Tablet:wacom/ } usb_probe() }
sub usbKeyboards { grep { $_-&gt;{media_type} =~ /\|Keyboard/ } usb_probe() }
sub usbStorage   { grep { $_-&gt;{media_type} =~ /Mass Storage\|/ } usb_probe() }

sub whatUsbport() {
    my ($i, $elem, @res) = (0, {});
    foreach (grep { $_-&gt;{media_type} =~ /Printer/ } usb_probe()) {
	my ($manufacturer, $model) = split '\|', $_-&gt;{description};
	$_-&gt;{description} =~ s/Hewlett[-\s_]Packard/HP/;
	push @res, { port =&gt; "/dev/usb/lp$i", val =&gt; { CLASS =&gt; 'PRINTER',
						       MODEL =&gt; $model,
						       MANUFACTURER =&gt; $manufacturer,
						       DESCRIPTION =&gt; $_-&gt;{description},
						     }};
	++$i;
    }
    @res;
}






sub whatPrinter() {
    my @res = (whatParport(), whatUsbport());
    grep { $_-&gt;{val}{CLASS} eq "PRINTER"} @res;
}

sub whatPrinterPort() {
    grep { tryWrite($_)} qw(/dev/lp0 /dev/lp1 /dev/lp2 /dev/usb/lp0 /dev/usb/lp1 /dev/usb/lp2);
}

sub probeSerialDevices {
    
    foreach (0..3) { devices::make("/dev/ttyS$_") }

    
    
    
    -d "/var/lock" or mkdir "/var/lock", 0755;
    -l "/dev/mouse" and $serialprobe{"/dev/" . readlink "/dev/mouse"} = undef;
    foreach (keys %serialprobe) { m|^/dev/(.*)| and touch "/var/lock/LCK..$1" }

    print STDERR "Please wait while probing serial ports...\n";
    
    
    local *F; open F, "$ENV{LD_LOADER} serial_probe |";
    local $_;
    my %current = (); while (&lt;F&gt;) {
	$serialprobe{$current{DEVICE}} = { %current } and %current = () if /^\s*$/ &amp;&amp; $current{DEVICE};
	$current{$1} = $2 if /^([^=]+)=(.*?)\s*$/;
    }
    close F;

    foreach (values %serialprobe) {
	$_-&gt;{DESCRIPTION} =~ /modem/i and $_-&gt;{CLASS} = 'MODEM'; 
	$_-&gt;{DESCRIPTION} =~ /olitec/i and $_-&gt;{CLASS} = 'MODEM'; 
	log::l("probed $_-&gt;{DESCRIPTION} of class $_-&gt;{CLASS} on device $_-&gt;{DEVICE}");
    }
}

sub probeSerial($) { $serialprobe{$_[0]} }

sub hasModem($) {
    $serialprobe{$_[0]} and $serialprobe{$_[0]}{CLASS} eq 'MODEM' and $serialprobe{$_[0]}{DESCRIPTION};
}

sub hasMousePS2 {
    my $t; sysread(tryOpen($_[0]) || return, $t, 256) != 1 || $t ne "\xFE";
}

sub raidAutoStartIoctl {
    eval { modules::load('md') };
    my $md = devices::make("md0");
    local *F;
    sysopen F, $md, 2 or return;
    ioctl F, 2324, 0;
}

sub raidAutoStart {
    log::l("raidAutoStart");
    my %personalities = ( '1' =&gt; 'linear', '2' =&gt; 'raid0', '3' =&gt; 'raid1', '4' =&gt; 'raid5' );
    raidAutoStartIoctl() or log::l("warning, RAID_AUTORUN not supported by kernel"), return;
    if (my @needed_perso = map { if_(/^kmod: failed.*md-personality-(.)/, $personalities{$1}) } syslog()) {
	log::l("RAID: autostart needs personality from $_"), eval { modules::load($_) } foreach @needed_perso;
	return raidAutoStartIoctl();
    } else {
	1;
    }
}




1; #

</pre></body></html>