From f928e6d72824dc8ac2a794e4a0f44135c1f166a2 Mon Sep 17 00:00:00 2001 From: Olivier Blin Date: Fri, 27 May 2005 11:36:31 +0000 Subject: initial import of network::thirdparty (this module factorizes the thirdparty software/drivers/firmwares detection and installation code, it points the user to the relevant packages/documentation/url if needed, and don't allow to configure a device if its requirements aren't satisfied) --- perl-install/network/netconnect.pm | 79 +------ perl-install/network/thirdparty.pm | 443 +++++++++++++++++++++++++++++++++++++ perl-install/network/tools.pm | 32 --- 3 files changed, 449 insertions(+), 105 deletions(-) create mode 100644 perl-install/network/thirdparty.pm (limited to 'perl-install/network') diff --git a/perl-install/network/netconnect.pm b/perl-install/network/netconnect.pm index d50b51453..4b5554cd5 100644 --- a/perl-install/network/netconnect.pm +++ b/perl-install/network/netconnect.pm @@ -12,6 +12,7 @@ use fs; use mouse; use network::network; use network::tools; +use network::thirdparty; use MDK::Common::Globals "network", qw($in); sub detect { @@ -85,7 +86,7 @@ sub real_main { my (%connections, @connection_list); my ($modem, $modem_name, $modem_conf_read, $modem_dyn_dns, $modem_dyn_ip); my $cable_no_auth; - my ($adsl_type, @adsl_devices, $adsl_failed, $adsl_answer, %adsl_cards, %adsl_data, $adsl_data, $adsl_provider, $adsl_old_provider, $adsl_vpi, $adsl_vci); + my ($adsl_type, @adsl_devices, %adsl_cards, %adsl_data, $adsl_data, $adsl_provider, $adsl_old_provider, $adsl_vpi, $adsl_vci); my ($ntf_name, $gateway_ex, $up, $need_restart_network); my ($isdn, $isdn_name, $isdn_type, %isdn_cards, @isdn_dial_methods); my $my_isdn = join('', N("Manual choice"), " (", N("Internal ISDN card"), ")"); @@ -775,28 +776,14 @@ Take a look at http://www.linmodems.org"), name => N("ADSL configuration") . "\n\n" . N("Select the network interface to configure:"), data => [ { label => N("Net Device"), type => "list", val => \$ntf_name, allow_empty_list => 1, list => \@adsl_devices, format => sub { $eth_intf{$_[0]} || $_[0] } } ], + complete => sub { + exists $adsl_cards{$ntf_name} && !network::thirdparty::setup_device($in, 'dsl', $adsl_cards{$ntf_name}[0]); + }, post => sub { - my %packages = ( - 'eci' => [ 'eciadsl', 'missing' ], - 'sagem' => [ 'eagle-usb', "/sbin/eaglectrl" ], - 'speedtouch' => [ 'speedtouch', "/usr/sbin/modem_run" ], - ); - return 'adsl_unsupported_eci' if $ntf_name eq 'eci'; if (exists $adsl_cards{$ntf_name}) { my $modem; ($ntf_name, $modem) = @{$adsl_cards{$ntf_name}}; - # FIXME: check that the package installation succeeds, else retry or abort - $in->do_pkgs->ensure_is_installed(@{$packages{$ntf_name}}) if $packages{$ntf_name}; - if ($ntf_name eq 'speedtouch') { - $in->do_pkgs->ensure_is_installed_if_available('speedtouch_mgmt', "/usr/share/speedtouch/mgmt.o"); - return 'adsl_speedtouch_firmware' if ! -e "$::prefix/usr/share/speedtouch/mgmt.o"; - } $netcnx->{bus} = $modem->{bus} if $ntf_name eq 'bewan'; - if ($ntf_name eq 'bewan' && !$::testing) { - if (my $unicorn_packages = $in->do_pkgs->check_kernel_module_packages('unicorn-kernel', 'unicorn')) { - $in->do_pkgs->install(@$unicorn_packages); - } - } } if (exists($isdn_cards{$ntf_name})) { require network::isdn; @@ -835,61 +822,6 @@ Take a look at http://www.linmodems.org"), }, - adsl_speedtouch_firmware => - { - name => N("You need the Alcatel microcode. -You can provide it now via a floppy or your windows partition, -or skip and do it later."), - data => [ { label => "", val => \$adsl_answer, type => "list", - list => [ N("Use a floppy"), N("Use my Windows partition"), N("Do it later") ], } - ], - post => sub { - my $destination = "$::prefix/usr/share/speedtouch/"; - my ($file, $source, $mounted); - if ($adsl_answer eq N("Use a floppy")) { - $mounted = 1; - $file = 'mgmt.o'; - ($source, $adsl_failed) = network::tools::use_floppy($in, $file); - } elsif ($adsl_answer eq N("Use my Windows partition")) { - ($source, $adsl_failed) = network::tools::use_windows($file = 'alcaudsl.sys'); - } - return "adsl_no_firmawre" if $adsl_answer eq N("Do it later"); - - my $_b = $mounted && before_leaving { fs::umount('/mnt') }; - if (!$adsl_failed) { - if (-e "$source/$file") { - cp_af("$source/$file", $destination) if !$::testing; - } else { - $adsl_failed = N("Firmware copy failed, file %s not found", $file); - } - } - log::explanations($adsl_failed || "Firmware copy $file in $destination succeeded"); - -e "$destination/alcaudsl.sys" and rename "$destination/alcaudsl.sys", "$destination/mgmt.o"; - - # kept translations b/c we may want to reuse it later: - my $_msg = N("Firmware copy succeeded"); - return $adsl_failed ? 'adsl_copy_firmware_failled' : 'adsl_provider'; - }, - }, - - - adsl_copy_firmware_failled => - { - name => sub { $adsl_failed }, - next => 'adsl_provider', - }, - - - "adsl_no_firmawre" => - { - name => N("You need the Alcatel microcode. -Download it at: -%s -and copy the mgmt.o in /usr/share/speedtouch", 'http://www.speedtouch.com/supuser.htm'), - next => "adsl_provider", - }, - - adsl_protocol => { pre => sub { @@ -1276,6 +1208,7 @@ See iwpriv(8) man page for further information."), $in->ask_warn(N("Error"), N("Could not install the %s package!", 'wpa_supplicant')); return 1; } + !network::thirdparty::setup_device($in, 'wireless', $module); }, post => sub { delete $ethntf->{WIRELESS_ENC_KEY}; diff --git a/perl-install/network/thirdparty.pm b/perl-install/network/thirdparty.pm new file mode 100644 index 000000000..23471aab2 --- /dev/null +++ b/perl-install/network/thirdparty.pm @@ -0,0 +1,443 @@ +package network::thirdparty; + +use strict; +use common; +use detect_devices; +use run_program; +use services; +use log; + +#- network_settings is an hash of categories (rtc, dsl, wireless, ...) +#- each category is an hash of device settings + +#- a device settings element must have the following fields: +#- o matching: +#- specify if this settings element matches a driver +#- can be a regexp, array ref or Perl code (parameters: driver) +#- o description: +#- full name of the device +#- o name: name used by the packages + +#- the following fields are optional: +#- o url: +#- url where the user can find tools/drivers/firmwares for this device +#- o device: +#- device in /dev to be configured +#- o post: +#- command to be run after all packages are installed +#- can be a shell command or Perl code +#- o restart_service: +#- if exists but not 1, name of the service to be restarted +#- if 1, specify that the service named by the name field should be restarted +#- o tools: +#- if exists but not 1, hash of the tools settings +#- if 1, tools are needed and package name is the name field +#- o kernel_module: +#- if exists but not 1, hash of the module settings +#- if 1, kernel modules are needed and use the name field +#- (name-kernel or dkms-name) +#- o firmware: +#- if exists but not 1, hash of the firmware settings +#- if 1, firmware are needed and use the name field +#- (name-firmware) + +#- hash of package settings structure (all fields are optional): +#- o package: +#- name of the package to be installed for these device +#- o test_file: +#- file used to test if the package is installed +#- o prefix: +#- path of the files that are tested +#- o links: +#- useful links for this device +#- can be a single link or array ref +#- o user_install: +#- function to call if the package installation fails +#- o explanations: +#- additionnal text to display if the installation fails + +my $hotplug_firmware_prefix = "$::prefix/lib/hotplug/firmware"; + +my %network_settings = ( + rtc => + [ + { + matching => qr/^Hcf:/, + description => 'HCF 56k Modem', + url => 'http://www.linuxant.com/drivers/hcf/', + name => 'hcfpcimodem', + kernel_module => 1, + tools => + { + test_file => '/usr/sbin/hcfpciconfig', + }, + device => '/dev/ttySHSF0', + post => '/usr/sbin/hcfpciconfig --auto', + }, + + { + matching => qr/^Hsf:/, + description => 'HSF 56k Modem', + url => 'http://www.linuxant.com/drivers/hsf/', + name => 'hsflinmodem', + kernel_module => 1, + tools => + { + test_file => '/usr/sbin/hsfconfig', + }, + device => '/dev/ttySHSF0', + post => '/usr/sbin/hsfconfig --auto', + }, + + { + matching => qr/^LT:/, + description => 'LT WinModem', + url => 'http://www.heby.de/ltmodem/', + name => 'ltmodem', + kernel_module => 1, + tools => + { + test_file => '/etc/devfs/conf.d/ltmodem.conf', + }, + device => '/dev/ttyS14', + links => + [ + 'http://linmodems.technion.ac.il/Ltmodem.html', + 'http://linmodems.technion.ac.il/packages/ltmodem/', + ], + }, + + { + matching => [ list_modules::category2modules('network/slmodem') ], + description => 'Smartlink WinModem', + url => 'http://www.smlink.com/content.aspx?id=135/', + name => 'slmodem', + kernel_module => 1, + tools => + { + test_file => '/usr/sbin/slmodemd', + }, + device => '/dev/ttySL0', + restart_service => 1, + }, + ], + + wireless => + [ + { + matching => 'zd1201', + description => 'ZyDAS ZD1201', + url => 'http://linux-lc100020.sourceforge.net/', + firmware => + { + test_file => 'zd1201*.fw', + }, + }, + + (map { ( + "ipw${_}" => + { + matching => "ipw${_}", + description => "Intel® PRO/Wireless ${_}", + url => "http://ipw${_}.sourceforge.net/", + name => "ipw${_}", + firmware => + { + test_file => ($_ == 2100 ? "ipw2100-*.fw" : "ipw-*.fw"), + }, + }, + ); + } (2100, 2200)), + + { + matching => 'prism54', + description => 'Prism GT / Prism Duette / Prism Indigo Chipsets', + url => 'http://prism54.org/', + name => 'prism54', + firmware => + { + url => 'http://prism54.org/~mcgrof/firmware/', + test_file => "isl38*", + }, + }, + + { + matching => qr/^at76c50/, + description => 'Atmel at76c50x cards', + url => 'http://thekelleys.org.uk/atmel/', + name => 'atmel', + firmware => + { + test_file => 'atmel_at76c50*', + }, + links => 'http://at76c503a.berlios.de/', + }, + ], + + dsl => + [ + { + matching => sub { detect_devices::getSpeedtouch() }, + description => N_("Alcatel speedtouch USB modem"), + url => "http://www.speedtouch.com/supuser.htm", + name => 'speedtouch', + tools => + { + test_file => '/usr/sbin/modem_run', + }, + firmware => + { + package => 'speedtouch_mgmt', + prefix => '/usr/share/speedtouch', + test_file => 'mgmt*.o', + explanations => N_("Copy the Alcatel microcode as mgmt.o in /usr/share/speedtouch/"), + user_install => \&install_speedtouch_microcode, + }, + links => 'http://linux-usb.sourceforge.net/SpeedTouch/mandrake/index.html', + }, + + { + matching => 'eciadsl', + url => 'http://eciadsl.flashtux.org/', + name => 'eciadsl', + tools => 1, + }, + + { + matching => 'eagle-usb', + description => 'Eagle chipset (from Analog Devices), e.g. Sagem F@st 800/840/908', + url => 'http://www.eagle-usb.org/', + name => 'eagle-usb', + tools => + { + test_file => '/sbin/eaglectrl', + }, + }, + + { + matching => 'bewan', + description => 'Bewan Adsl (Unicorn)', + url => 'http://www.bewan.com/bewan/users/downloads/', + name => 'unicorn', + kernel_module => 1, + tools => 1, + }, + ], +); + +sub device_get_package { + my ($settings, $option, $o_default) = @_; + $settings->{$option} or return; + my $package; + if (ref $settings->{$option} eq 'HASH') { + $package = $settings->{$option}{package} || 1; + } else { + $package = $settings->{$option}; + } + $package == 1 ? $o_default || $settings->{name} : $package; +} + +sub device_get_option { + my ($settings, $option) = @_; + $settings->{$option} or return; + my $value = $settings->{$option}; + $value == 1 ? $settings->{name} : $value; +} + +sub find_settings { + my ($category, $driver) = @_; + find { + my $type = ref $_->{matching}; + $type eq 'Regexp' && $driver =~ $_->{matching} || + $type eq 'CODE' && $_->{matching}->($driver) || + $type eq 'ARRAY' && member($driver, @{$_->{matching}}) || + $driver eq $_->{matching}; + } @{$network_settings{$category}}; +} + +sub warn_not_installed { + my ($in, @packages) = @_; + $in->ask_warn(N("Error"), N("Could not install the packages (%s)!", @packages)); +} + +sub warn_not_found { + my ($in, $settings, $option, @packages) = @_; + my ($url, $expl); + if (ref $settings->{$option}) { + $url = $settings->{$option}{url}; + $expl = $settings->{$option}{explanations}; + } + $url ||= $settings->{url}; + $in->ask_warn(N("Error"), + N("Some packages (%s) are required but aren't available. They can be found in Mandriva Club or in Mandriva commercial releases.", @packages) . + if_($url, "\n\n" . N("The required files can also be installed from this URL: +%s", $url)) . + if_($expl, "\n\n" . translate($expl))); +} + +sub is_file_installed { + my ($settings, $option) = @_; + my $file = exists $settings->{$option} && $settings->{$option}{test_file}; + $file && -e "$::prefix$file"; +} + +sub is_module_installed { + my ($driver) = @_; + find { m!/\Q$driver\E\.k?o! } cat_("$::prefix/lib/modules/" . c::kernel_version() . '/modules.dep'); +} + +sub is_firmware_installed { + my ($settings) = @_; + my $wildcard = exists $settings->{firmware} && $settings->{firmware}{test_file} or return; + my $path = $settings->{firmware}{prefix} || $hotplug_firmware_prefix; + scalar glob_("$::prefix$path/$wildcard"); +} + +sub find_file_on_windows_system { + my ($in, $file) = @_; + my $source; + require fsedit; + my $all_hds = fsedit::get_hds(); + fs::get_info_from_fstab($all_hds); + if (my $part = find { $_->{device_windobe} eq 'C' } fs::get::fstab($all_hds)) { + foreach (qw(windows/system winnt/system windows/system32/drivers winnt/system32/drivers)) { + -d $_ and $source = first(glob_("$part->{mntpoint}/$_/$file")) and last; + } + $source or $in->ask_warn(N("Error"), N("Unable to find \"%s\" on your Windows system!", $file)); + } else { + $in->ask_warn(N("Error"), N("No Windows system has been detected!")); + } + { file => $source }; +} + +sub find_file_on_floppy { + my ($in, $file) = @_; + my $floppy = detect_devices::floppy(); + my $mountpoint = '/mnt/floppy'; + my $h; + $in->ask_okcancel(N("Insert floppy"), + N("Insert a FAT formatted floppy in drive %s with %s in root directory and press %s", $floppy, $file, N("Next"))) or return; + if (eval { fs::mount(devices::make($floppy), $mountpoint, 'vfat', 'readonly'); 1 }) { + log::explanations("Mounting floppy device $floppy in $mountpoint"); + $h = before_leaving { fs::umount($mountpoint) }; + if ($h->{file} = first(glob("$mountpoint/$file"))) { + log::explanations("Found $h->{file} on floppy device"); + } else { + log::explanations("Unabled to find $file on floppy device"); + } + } else { + $in->ask_warn(N("Error"), N("Floppy access error, unable to mount device %s", $floppy)); + log::explanations("Unable to mount floppy device $floppy"); + } + $h; +} + +sub install_speedtouch_microcode { + my ($in) = @_; + my $choice; + $in->ask_from('', + N("You need the Alcatel microcode. +You can provide it now via a floppy or your windows partition, +or skip and do it later."), + [ { type => "list", val => \$choice, format => \&translate, + list => [ N_("Use a floppy"), N_("Use my Windows partition") ] } ]) or return; + my ($h, $source); + if ($choice eq N_("Use a floppy")) { + $source = 'mgmt*.o'; + $h = find_file_on_floppy($in, $source); + } else { + $source = 'alcaudsl.sys'; + $h = find_file_on_windows_system($in, $source); + } + unless (-e $h->{file} && cp_f($h->{file}, "$::prefix/usr/share/speedtouch/mgmt.o")) { + $in->ask_warn(N("Error"), N("Firmware copy failed, file %s not found", $source)); + log::explanations("Firmware copy of $source ($h->{file}) failed"); + return; + } + log::explanations("Firmware copy of $h->{file} succeeded"); + $in->ask_warn(N("Congratulations!"), N("Firmware copy succeeded")); + 1; +} + +sub install_packages { + my ($in, $settings, $driver, @options) = @_; + + foreach my $option (@options) { + my %methods = + ( + default => + { + find_package_name => sub { device_get_package($settings, $option) }, + check_installed => sub { is_file_installed($settings, $option) }, + get_packages => sub { my ($name) = @_; $in->do_pkgs->is_available($name) }, + user_install => sub { my $f = $settings->{$option}{user_install}; $f && $f->($in) }, + }, + kernel_module => + { + find_package_name => sub { device_get_package($settings, $option, "$settings->{name}-kernel") }, + check_installed => sub { is_module_installed($driver) }, + get_packages => sub { my ($name) = @_; my $l = $in->do_pkgs->check_kernel_module_packages($name); $l ? @$l : () } + }, + firmware => + { + find_package_name => sub { device_get_package($settings, $option, "$settings->{name}-firmware") }, + check_installed => sub { is_firmware_installed($settings) }, + }, + ); + my $get_method = sub { my ($method) = @_; exists $methods{$option} && $methods{$option}{$method} || $methods{default}{$method} }; + + my $name = $get_method->('find_package_name')->(); + unless ($name) { + log::explanations(qq(No $option package for module "$driver" is required, skipping)); + next; + } + + if ($get_method->('check_installed')->()) { + log::explanations(qq(Required $option package for module "$driver" is already installed, skipping)); + next; + } + + if (my @packages = $get_method->('get_packages')->($name)) { + log::explanations("Installing thirdparty packages ($option) " . join(', ', @packages)); + $in->do_pkgs->install(@packages) and next; + warn_not_installed($in, @packages); + } + log::explanations("Thirdparty package $name ($option) is required but not available"); + + unless ($get_method->('user_install')->($in)) { + warn_not_found($in, $settings, $option, $name); + return; + } + } + + 1; +} + +sub setup_device { + my ($in, $category, $driver) = @_; + if (my $settings = find_settings($category, $driver)) { + log::explanations(qq(Found settings for driver "$driver" in category "$category")); + + my $_w = $in->wait_message('', N("Looking for required software and drivers...")); + + install_packages($in, $settings, $driver, qw(kernel_module firmware tools)) or return; + + if (my $service = device_get_option($settings, 'service')) { + log::explanations("Restarting service $service"); + services::restart_or_start($service); + } + + if (my $post = $settings->{post}) { + my $_w = $in->wait_message('', N("Please wait, running device configuration commands...")); + log::explanations("Running post-install command $post"); + run_program::rooted($::prefix, $post); + } + + log::explanations(qq(Settings for driver "$driver" applied)); + } else { + log::explanations(qq(No settings found for driver "$driver" in category "$category")); + } + 1; +} + +1; diff --git a/perl-install/network/tools.pm b/perl-install/network/tools.pm index 6ba1d9886..ba51572a7 100644 --- a/perl-install/network/tools.pm +++ b/perl-install/network/tools.pm @@ -3,7 +3,6 @@ package network::tools; # $Id$ use strict; use common; use run_program; -use fsedit; use c; use vars qw(@ISA @EXPORT @EXPORT_OK); use MDK::Common::System qw(getVarsFromSh); @@ -169,37 +168,6 @@ sub remove_initscript() { } } -sub use_windows { - my ($file) = @_; - my $all_hds = fsedit::get_hds(); - fs::get_info_from_fstab($all_hds); - if (my $part = find { $_->{device_windobe} eq 'C' } fs::get::fstab($all_hds)) { - my $source = find { -d $_ && -r "$_/$file" } map { "$part->{mntpoint}/$_" } qw(windows/system winnt/system windows/system32/drivers winnt/system32/drivers); - log::explanations("Seek in $source to find firmware"); - $source; - } else { - my $failed = N("No partition available"); - log::explanations($failed); - undef, $failed; - } -} - -sub use_floppy { - my ($in, $file) = @_; - my $floppy = detect_devices::floppy(); - $in->ask_okcancel(N("Insert floppy"), - N("Insert a FAT formatted floppy in drive %s with %s in root directory and press %s", $floppy, $file, N("Next"))) or return; - if (eval { fs::mount(devices::make($floppy), '/mnt', 'vfat', 'readonly'); 1 }) { - log::explanations("Mounting floppy device $floppy in /mnt"); - '/mnt'; - } else { - my $failed = N("Floppy access error, unable to mount device %s", $floppy); - log::explanations($failed); - undef, $failed; - } -} - - sub is_dynamic_ip { my ($intf) = @_; any { $_->{BOOTPROTO} !~ /^(none|static|)$/ } values %$intf; -- cgit v1.2.1