diff options
Diffstat (limited to 'perl-install/detect_devices.pm')
| -rw-r--r-- | perl-install/detect_devices.pm | 272 |
1 files changed, 171 insertions, 101 deletions
diff --git a/perl-install/detect_devices.pm b/perl-install/detect_devices.pm index 5e573574d..2361f3f9d 100644 --- a/perl-install/detect_devices.pm +++ b/perl-install/detect_devices.pm @@ -34,7 +34,7 @@ sub get() { getIDE(), getSCSI(), getDAC960(), getCompaqSmartArray(), getATARAID(); } -sub hds() { grep { $_->{media_type} eq 'hd' && !isRemovableDrive($_) } get() } +sub hds() { grep { may_be_a_hd($_) } get() } sub tapes() { grep { $_->{media_type} eq 'tape' } get() } sub cdroms() { grep { $_->{media_type} eq 'cdrom' } get() } sub burners() { grep { isBurner($_) } cdroms() } @@ -52,7 +52,7 @@ sub zips() { sub floppies() { require modules; - eval { modules::load("floppy") }; + eval { modules::load("floppy") } if $::isInstall; my @fds = $@ ? () : map { my $info = (!dev_is_devfs() || -e "/dev/fd$_") && c::floppy_info(devices::make("fd$_")); if_($info && $info ne '(null)', { device => "fd$_", devfs_device => "floppy/$_", media_type => 'fd', info => $info }) @@ -175,12 +175,26 @@ sub isDvdDrive { sub isZipDrive { $_[0]{info} =~ /ZIP\s+\d+/ } #- accept ZIP 100, untested for bigger ZIP drive. sub isJazzDrive { $_[0]{info} =~ /\bJAZZ?\b/i } #- accept "iomega jaz 1GB" sub isLS120Drive { $_[0]{info} =~ /LS-?120|144MB/ } -sub isRemovableUsb { $_[0]{usb_media_type} && index($_[0]{usb_media_type}, 'Mass Storage') == 0 && usb2removable($_[0]) } -sub isKeyUsb { $_[0]{usb_media_type} && index($_[0]{usb_media_type}, 'Mass Storage') == 0 && $_[0]{media_type} eq 'hd' } +sub isRemovableUsb { begins_with($_[0]{usb_media_type} || '', 'Mass Storage') && usb2removable($_[0]) } +sub isKeyUsb { begins_with($_[0]{usb_media_type} || '', 'Mass Storage') && $_[0]{media_type} eq 'hd' } sub isFloppyUsb { $_[0]{usb_driver} && $_[0]{usb_driver} eq 'Removable:floppy' } -sub isRemovableDrive { +sub may_be_a_hd { my ($e) = @_; - isZipDrive($e) || isLS120Drive($e) || $e->{media_type} && $e->{media_type} eq 'fd' || isRemovableUsb($e) || $e->{usb_media_type} && index($e->{usb_media_type}, 'Mass Storage|Floppy (UFI)') == 0; + $e->{media_type} eq 'hd' && !( + isZipDrive($e) + || isLS120Drive($e) + || begins_with($e->{usb_media_type} || '', 'Mass Storage|Floppy (UFI)') + ); +} + +sub get_scsi_driver { + my (@l) = @_; + my %host2driver = map { if_(m!.*/(.*)/(.*)!, $2, $1) } glob("/proc/scsi/*/*"); + foreach (@l) { + if (my $driver = $host2driver{$_->{host}}) { + $_->{driver} = $driver; + } + } } sub getSCSI_24() { @@ -222,6 +236,7 @@ sub getSCSI_24() { get_devfs_devices(@l); get_sys_cdrom_info(@l); + get_scsi_driver(@l); @l; } @@ -270,6 +285,8 @@ sub getSCSI_26() { }; } all($dev_dir); + @l = sort { $a->{host} <=> $b->{host} || $a->{channel} <=> $b->{channel} || $a->{id} <=> $b->{id} || $a->{lun} <=> $b->{lun} } @l; + complete_usb_storage_info(@l); foreach (@l) { @@ -278,6 +295,7 @@ sub getSCSI_26() { get_devfs_devices(@l); get_sys_cdrom_info(@l); + get_scsi_driver(@l); @l; } sub getSCSI() { c::kernel_version() =~ /^\Q2.6/ ? getSCSI_26() : getSCSI_24() } @@ -344,6 +362,12 @@ sub getIDE() { @idi; } +sub block_devices() { + -d '/sys/block' + ? map { s|!|/|; $_ } all('/sys/block') + : map { $_->{dev} } devices::read_proc_partitions_raw(); +} + sub getCompaqSmartArray() { my (@idi, $f); @@ -353,12 +377,14 @@ sub getCompaqSmartArray() { my ($name) = m|/(.*)|; for (my $i = 0; -r ($f = "${prefix}$i"); $i++) { - foreach (cat_($f)) { - if (my ($raw_device) = m|^\s*($name/.*?):|) { - my $device = -d "/dev/$raw_device" ? "$raw_device/disc" : $raw_device; - push @idi, { device => $device, prefix => $raw_device . 'p', info => "Compaq RAID logical disk", - media_type => 'hd', bus => 'ida' }; - } + my @raw_devices = cat_($f) =~ m|^\s*($name/.*?):|gm; + @raw_devices or @raw_devices = grep { m!^$name/! } block_devices(); + + foreach my $raw_device (@raw_devices) { + my $device = -d "/dev/$raw_device" ? "$raw_device/disc" : $raw_device; + push @idi, { device => $device, prefix => $raw_device . 'p', + info => "Compaq RAID logical disk", + media_type => 'hd', bus => $name }; } } } @@ -412,7 +438,7 @@ sub getCPUs() { } sub getSoundDevices() { - (arch() =~ /ppc/ ? \&modules::load_category : \&modules::probe_category)->('multimedia/sound'); + modules::probe_category('multimedia/sound'); } sub isTVcard { member($_[0]{driver}, qw(bttv cx8800 saa7134 usbvision)) } @@ -421,8 +447,29 @@ sub getTVcards() { grep { isTVcard($_) } detect_devices::probeall(); } +sub getInputDevices() { + my (@devices, $device); + foreach (cat_('/proc/bus/input/devices')) { + if (/^I:/) { + push @devices, $device if $device; + $device = {}; + $device->{vendor} = $1 if /Vendor=([0-9a-f]+)/; + $device->{id} = $1 if /Product=([0-9a-f]+)/; + } + $device->{description} = "|$1" if /N: Name="(.*)"/; + $device->{driver} = $1 if /H: Handlers=(\w+)/; + if (/P: Phys=(.*)/) { + $device->{location} = $1; + $device->{bus} = 'isa' if $device->{location} =~ /^isa/; + $device->{bus} = 'usb' if $device->{location} =~ /^usb/i; + } + } + push @devices, $device if $device; + @devices; +} + sub getSerialModem { - my ($o_mouse) = @_; + my ($modules_conf, $o_mouse) = @_; my $mouse = $o_mouse || {}; $mouse->{device} = readlink "/dev/mouse"; my $serdev = arch() =~ /ppc/ ? "macserial" : "serial"; @@ -441,14 +488,16 @@ sub getSerialModem { my @devs = pcmcia_probe(); foreach my $modem (@modems) { #- add an alias for macserial on PPC - modules::set_alias('serial', $serdev) if arch() =~ /ppc/ && $modem->{device}; + $modules_conf->set_alias('serial', $serdev) if arch() =~ /ppc/ && $modem->{device}; foreach (@devs) { $_->{type} =~ /serial/ and $modem->{device} = $_->{device} } } @modems; } -sub getModem() { - getSerialModem({}), matching_driver('www\.linmodems\.org'); +sub getModem { + my ($modules_conf) = @_; + getSerialModem($modules_conf, {}), matching_driver__regexp('www\.linmodems\.org'), + matching_driver('ltmodem', list_modules::category2modules('network/slmodem')); } sub getSpeedtouch() { @@ -456,11 +505,10 @@ sub getSpeedtouch() { } sub getBewan() { - grep { $_->{description} =~ /Bewan Systems\|PCI ADSL Modem|BEWAN ADSL USB/ } probeall(); - + matching_desc__regexp('Bewan Systems\|.*ADSL|BEWAN ADSL USB'); } sub getSagem() { - grep { member($_->{driver}, qw(adiusbadsl eagle-usb)) } probeall(); + matching_driver(qw(adiusbadsl eagle-usb)); } # generate from the following from eci driver sources: @@ -511,7 +559,7 @@ sub getNet() { grep { !/^(?:lo|ippp|isdn|plip|ppp|sit0)/ } uniq( - (map { if_(/^\s*([A-Za-z0-9:\.]*):\s/, $1) } cat_("/proc/net/dev")), + (map { if_(/^\s*([A-Za-z0-9:\.]*):/, $1) } cat_("/proc/net/dev")), c::get_netdevices(), ); } @@ -520,29 +568,27 @@ sub getNet() { # mapgrep(sub {member (($_[0] =~ /\s*(\w*):/), @netdevices), $1 }, split(/\n/, cat_("/proc/net/dev"))); #} -# heavily inspirated from hidups driver from nut: sub getUPS() { - # nut/driver/hidups.h: - my $UPS_USAGE = 0x840004; - my $POWER_USAGE = 0x840020; - my $hiddev_find_application = sub { - my ($fd, $usage) = @_; - my $i = 0; - my $ret; - do { $i++ } while ($ret = ioctl($fd, c::HIDIOCAPPLICATION(), $i)) && $ret != $usage; - return $ret == $usage ? 1 : 0; - }; - - (map { $_->{driver} = "mge-shut"; $_ } grep { $_->{DESCRIPTION} =~ /MGE UPS/ } values %serialprobe), + # MGE serial PnP devices: + my @usb_devices = map { ($_->{name} = $_->{description}) =~ s/.*\|//; $_ } usb_probe(); + (map { - open(my $f, $_); - if_(!$hiddev_find_application->($f, $UPS_USAGE) && !$hiddev_find_application->($f, $POWER_USAGE), - { port => $_, - name => c::get_usb_ups_name(fileno($f)), - driver => "hidups", - } - ); - } -e "/dev/.devfsd" ? glob("/dev/usb/hid/hiddev*") : glob("/dev/usb/hiddev*")); + $_->{port} = $_->{DEVICE}; + $_->{bus} = "Serial"; + $_->{driver} = "mge-utalk" if $_->{MODEL} =~ /0001/; + $_->{driver} = "mge-shut" if $_->{MODEL} =~ /0002/; + $_->{media_type} = 'UPS'; + $_->{description} = "MGE UPS SYSTEMS|UPS - Uninterruptible Power Supply" if $_->{MODEL} =~ /000[12]/; + $_; + } grep { $_->{DESCRIPTION} =~ /MGE UPS/ } values %serialprobe), + # USB UPSs; + (grep { $_->{description} =~ /American Power Conversion\|Back-UPS/ } @usb_devices), + (map { + $_->{port} = "auto"; + $_->{media_type} = 'UPS'; + $_->{driver} = 'newhidups'; + $_; + } grep { $_->{driver} =~ /ups$/ } @usb_devices); } $pcitable_addons = <<'EOF'; @@ -609,7 +655,19 @@ sub usb_probe() { } sub firewire_probe() { - my ($e, @l); + my $dev_dir = '/sys/bus/ieee1394/devices'; + my @l = map { + my $dir = "$dev_dir/$_"; + my $get = sub { chomp_(cat_($_[0])) }; + { + version => hex($get->("$dir/../vendor_id")), + specifier_id => hex($get->("$dir/specifier_id")), + specifier_version => hex($get->("$dir/version")), + bus => 'Firewire', + } + } grep { -f "$dev_dir/$_/specifier_id" } all($dev_dir); + + my $e; foreach (cat_('/proc/bus/ieee1394/devices')) { if (m!Vendor/Model ID: (.*) \[(\w+)\] / (.*) \[(\w+)\]!) { push @l, $e = { @@ -623,14 +681,23 @@ sub firewire_probe() { $e->{specifier_version} = hex $1; } } + foreach (@l) { - if ($e->{specifier_id} == 0x00609e && $e->{specifier_version} == 0x010483) { + if ($_->{specifier_id} == 0x00609e && $_->{specifier_version} == 0x010483) { add2hash($_, { driver => 'sbp2', description => "Generic Firewire Storage Controller" }); + } elsif ($_->{specifier_id} == 0x00005e && $_->{specifier_version} == 0x000001) { + add2hash($_, { driver => 'eth1394', description => "IEEE 1394 IPv4 Driver (IPv4-over-1394 as per RFC 2734)" }); } } @l; } +sub real_pcmcia_probe() { + return if $::testing; + + c::pcmcia_probe() || (find { $_->{driver} eq 'yenta_socket' } pci_probe()) && 'yenta_socket'; +} + sub pcmcia_probe() { -e '/var/run/stab' || -e '/var/lib/pcmcia/stab' or return (); @@ -654,14 +721,20 @@ sub probeall() { require sbus_probing::main; pci_probe(), usb_probe(), firewire_probe(), pcmcia_probe(), sbus_probing::main::probe(); } -sub matching_desc { +sub matching_desc__regexp { my ($regexp) = @_; grep { $_->{description} =~ /$regexp/i } probeall(); } -sub matching_driver { +sub matching_driver__regexp { my ($regexp) = @_; grep { $_->{driver} =~ /$regexp/i } probeall(); } + +sub matching_driver { + my (@list) = @_; + grep { member($_->{driver}, @list) } probeall(); +} + sub stringlist() { map { sprintf("%-16s: %s%s%s", @@ -715,19 +788,60 @@ sub hasSMP() { } sub hasPCMCIA() { $::o->{pcmcia} } #- because /proc/pcmcia seems not to be present on 2.4 at least (or use /var/run/stab) +sub dmidecode() { + my (%l, $cat); + + my $dmidecode_infos if 0; + + if (!$dmidecode_infos) { + foreach (run_program::get_stdout('dmidecode')) { + if (/^\t\t(.*)/) { + $l{$cat} .= "$1\n"; + } elsif (my ($s) = /^\t(.*)/) { + next if $s =~ /^DMI type /; + $s =~ s/ Information$//; + $cat = $s; + } + } + my $Chassis = $l{Chassis} =~ /^Type:\s*(\S+)/m && $1; + my $BIOS_Year = $l{BIOS} =~ m!^Release Date:.*?(\d{4})!m && $1 || + $l{BIOS} =~ m!^Release Date:.*?\d\d/\d\d/(\d\d)!m && "20$1"; + + $dmidecode_infos = { + isLaptop => member($Chassis, 'Portable', 'Laptop', 'Notebook', 'Sub Notebook', 'Docking Station'), + if_($BIOS_Year, BIOS_Year => $BIOS_Year), + }; + } + $dmidecode_infos; +} + #- try to detect a laptop, we assume pcmcia service is an indication of a laptop or #- the following regexp to match graphics card apparently only used for such systems. sub isLaptop() { - hasPCMCIA() || (matching_desc('C&T.*655[45]\d') || matching_desc('C&T.*68554') || - matching_desc('Neomagic.*Magic(Media|Graph)') || - matching_desc('ViRGE.MX') || matching_desc('S3.*Savage.*[IM]X') || - matching_desc('ATI.*(Mobility|LT)')) - || cat_('/proc/cpuinfo') =~ /\bmobile\b/i; + arch() =~ /ppc/ ? + get_mac_model() =~ /Book/ : + dmidecode()->{isLaptop} + || (matching_desc__regexp('C&T.*655[45]\d') || matching_desc__regexp('C&T.*68554') || + matching_desc__regexp('Neomagic.*Magic(Media|Graph)') || + matching_desc__regexp('ViRGE.MX') || matching_desc__regexp('S3.*Savage.*[IM]X') || + matching_desc__regexp('ATI.*(Mobility|LT)')) + || cat_('/proc/cpuinfo') =~ /\bmobile\b/i; +} + +sub is_i586() { + my $cpuinfo = cat_('/proc/cpuinfo'); + $cpuinfo =~ /^cpu family\s*:\s*(\d+)/m && $1 < 6 || + $cpuinfo !~ /^flags.*\bcmov\b/m; +} + +sub matching_type { + my ($type) = @_; + $type =~ /laptop/i && isLaptop(); } -sub usbMice() { grep { $_->{media_type} =~ /\|Mouse/ && $_->{driver} !~ /Tablet:wacom/ || +sub usbMice() { grep { $_->{media_type} =~ /\|Mouse/ && $_->{driver} !~ /wacom/ || $_->{driver} =~ /Mouse:USB/ } usb_probe() } -sub usbWacom() { grep { $_->{driver} =~ /Tablet:wacom/ } usb_probe() } +sub usbWacom() { grep { $_->{driver} =~ /wacom/ } usb_probe() } sub usbKeyboards() { grep { $_->{media_type} =~ /\|Keyboard/ } usb_probe() } sub usbStorage() { grep { $_->{media_type} =~ /Mass Storage\|/ } usb_probe() } @@ -785,49 +899,6 @@ sub hasMousePS2 { my $t; sysread(tryOpen($_[0]) || return, $t, 256) != 1 || $t ne "\xFE"; } -sub raidAutoStartIoctl() { - sysopen(my $F, devices::make("md0"), 2) or return; - ioctl $F, 0x914, 0; #- RAID_AUTORUN -} - -sub raidAutoStartRaidtab { - my (@parts) = @_; - $::isInstall or return; - require raid; - #- faking a raidtab, it seems to be working :-))) - #- (choosing any inactive md) - raid::inactivate_all(); - my $detect_one = sub { - my ($device) = @_; - my $free_md = devices::make(find { !raid::is_active($_) } map { "md$_" } 0 .. raid::max_nb()); - output("/tmp/raidtab", "raiddev $free_md\n device " . devices::make($device) . "\n"); - log::l("raidAutoStartRaidtab: trying $device"); - run_program::run('raidstart', '-c', "/tmp/raidtab", $free_md); - }; - $detect_one->($_->{device}) foreach @parts; - - #- try again to detect RAID 10 - $detect_one->($_) foreach raid::active_mds(); - - unlink "/tmp/raidtab"; -} - -sub raidAutoStart { - my (@parts) = @_; - - log::l("raidAutoStart"); - eval { modules::load('md') }; - my %personalities = ('1' => 'linear', '2' => 'raid0', '3' => 'raid1', '4' => 'raid5'); - raidAutoStartIoctl() or raidAutoStartRaidtab(@parts); - foreach (1..2) { #- try twice for RAID 10 - my @needed_perso = map { - if_(/^kmod: failed.*md-personality-(.)/ || - /^md: personality (.) is not loaded/, $personalities{$1}) } syslog() or last; - eval { modules::load(@needed_perso) }; - raidAutoStartIoctl() or raidAutoStartRaidtab(@parts); - } -} - sub usb_description2removable { local ($_) = @_; return 'camera' if /\bcamera\b/i; @@ -854,13 +925,12 @@ sub suggest_mount_point { my ($e) = @_; my $name = $e->{media_type}; - if (member($name, 'hd', 'fd')) { + if (member($e->{media_type}, 'hd', 'fd')) { if (exists $e->{usb_driver}) { - return usb2removable($e) || 'removable'; - } - if (isZipDrive($e)) { + $name = usb2removable($e) || 'removable'; + } elsif (isZipDrive($e)) { $name = 'zip'; - } elsif ($name eq 'fd') { + } elsif ($e->{media_type} eq 'fd') { $name = 'floppy'; } else { log::l("suggest_mount_point: don't know what to with hd $e->{device}"); |
