From 6eea717617247c8932c5fe82f1ff0c5278b12237 Mon Sep 17 00:00:00 2001 From: Olivier Blin Date: Tue, 19 Apr 2005 21:29:26 +0000 Subject: improve ndiswrapper driver configuration (allow to select driver, device and many errors handling) --- perl-install/network/netconnect.pm | 111 ++++++++++++++++++++++++------------- perl-install/network/wireless.pm | 103 +++++++++++++++++++++++++++++----- 2 files changed, 161 insertions(+), 53 deletions(-) diff --git a/perl-install/network/netconnect.pm b/perl-install/network/netconnect.pm index dbfdc82e0..9441ae61c 100644 --- a/perl-install/network/netconnect.pm +++ b/perl-install/network/netconnect.pm @@ -89,7 +89,7 @@ sub real_main { 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"), ")"); - my ($ndiswrapper_driver, $ndiswrapper_inf_file); + my (@ndiswrapper_drivers, $ndiswrapper_driver, $ndiswrapper_device); my ($is_wireless, $wireless_key, $wireless_use_wpa); my ($module, $auto_ip, $protocol, $onboot, $needhostname, $peerdns, $peeryp, $peerntpd, $hotplug, $track_network_id); # lan config my $success = 1; @@ -240,6 +240,42 @@ sub real_main { } }; + my $ndiswrapper_do_device_selection = sub { + $ntf_name = network::wireless::ndiswrapper_setup_device($in, $ndiswrapper_device); + unless ($ntf_name) { + undef $ndiswrapper_device; + return; + } + + #- redetect interfaces (so that the ndiswrapper module can be detected) + $lan_detect->(); + + $ethntf = $intf->{$ntf_name} ||= { DEVICE => $ntf_name }; + + 1; + }; + + my $ndiswrapper_do_driver_selection = sub { + my @devices = network::wireless::ndiswrapper_get_devices($in, $ndiswrapper_driver); + + if (!@devices) { + undef $ndiswrapper_driver; + return; + } elsif (@devices == 1) { + #- only one device matches installed driver + $ndiswrapper_device = $devices[0]; + return $ndiswrapper_do_device_selection->(); + } + + 1; + }; + + my $ndiswrapper_next_step = sub { + return $ndiswrapper_device ? 'lan_protocol' : + $ndiswrapper_driver ? 'ndiswrapper_select_device' : + 'ndiswrapper_select_driver'; + }; + use locale; set_l10n_sort(); @@ -958,12 +994,30 @@ You can find a driver on http://eciadsl.flashtux.org/"), [ { label => N("Net Device"), type => "list", val => \$ntf_name, list => [ (sort keys %eth_intf), N_("Manually load a driver"), if_($is_wireless, N_("Use a Windows driver (with ndiswrapper)")) ], allow_empty_list => 1, format => sub { translate($eth_intf{$_[0]} || $_[0]) } } ]; }, + complete => sub { + if ($ntf_name eq "Use a Windows driver (with ndiswrapper)") { + require network::wireless; + unless ($in->do_pkgs->ensure_is_installed('ndiswrapper', '/usr/sbin/ndiswrapper')) { + $in->ask_warn(N("Error"), N("Could not install the %s package!", 'ndiswrapper')); + return 1; + } + undef $ndiswrapper_driver; + undef $ndiswrapper_device; + unless (network::wireless::ndiswrapper_installed_drivers()) { + if ($ndiswrapper_driver = network::wireless::ndiswrapper_ask_driver($in)) { + return !$ndiswrapper_do_driver_selection->(); + } + return 1; + } + } + 0; + }, post => sub { if ($ntf_name eq "Manually load a driver") { modules::interactive::load_category__prompt($in, $modules_conf, list_modules::ethernet_categories()); return 'lan'; } elsif ($ntf_name eq "Use a Windows driver (with ndiswrapper)") { - return 'ndiswrapper'; + return $ndiswrapper_next_step->(); } $ethntf = $intf->{$ntf_name} ||= { DEVICE => $ntf_name }; $::isInstall && $netc->{NET_DEVICE} eq $ethntf->{DEVICE} ? 'lan_alrd_cfg' : 'lan_protocol'; @@ -1115,56 +1169,35 @@ notation (for example, 1.2.3.4).")), }, }, - ndiswrapper => + ndiswrapper_select_driver => { pre => sub { - require network::wireless; + @ndiswrapper_drivers = network::wireless::ndiswrapper_installed_drivers(); + $ndiswrapper_driver ||= first(@ndiswrapper_drivers); }, data => sub { - my @drv = network::wireless::ndiswrapper_installed_drivers(); [ { label => N("Choose an ndiswrapper driver"), type => "list", val => \$ndiswrapper_driver, allow_empty_list => 1, - list => [ N("Install a new driver"), if_(@drv, N("Use already installed driver (%s)", join(", ", @drv))) ] } ]; + list => [ undef, @ndiswrapper_drivers ], + format => sub { defined $_[0] ? N("Use the ndiswrapper driver %s", $_[0]) : N("Install a new driver") } } ]; }, complete => sub { - unless ($in->do_pkgs->ensure_is_installed('ndiswrapper', '/usr/sbin/ndiswrapper')) { - $in->ask_warn(N("Error"), N("Could not install the %s package!", 'ndiswrapper')); - return 1; - } - if ($ndiswrapper_driver eq N("Install a new driver")) { - if ($ndiswrapper_inf_file = $in->ask_file(N("Please select the Windows driver (.inf file)"), "/mnt/cdrom")) { - return system('ndiswrapper', '-i', $ndiswrapper_inf_file); - } - return 1; - } + $ndiswrapper_driver ||= network::wireless::ndiswrapper_ask_driver($in) or return 1; + !$ndiswrapper_do_driver_selection->(); }, - post => sub { - if (keys %eth_intf) { - return 'ndiswrapper_intf'; - } else { - $ntf_name = network::wireless::ndiswrapper_setup(); - $ethntf = $intf->{$ntf_name} ||= { DEVICE => $ntf_name }; - return 'lan_protocol'; - } - } + post => $ndiswrapper_next_step, }, - ndiswrapper_intf => + ndiswrapper_select_device => { - pre => sub { - undef $ntf_name; - }, - data => sub { - [ { label => N("Net Device"), type => "list", val => \$ntf_name, list => [ sort keys %eth_intf ], - format => sub { translate($eth_intf{$_[0]}) } } ]; + data => sub { + [ { label => N("Select a device:"), type => "list", val => \$ndiswrapper_device, allow_empty_list => 1, + list => [ network::wireless::ndiswrapper_present_devices($ndiswrapper_driver) ], + format => sub { $_[0]{description} } } ]; }, - post => sub { - #- if another module is loaded for the wireless interface, unload it before using ndiswrapper - my $eth = find { $_->[0] eq $ntf_name } @all_cards; - $eth and modules::unload($eth->[1]); - $ntf_name = network::wireless::ndiswrapper_setup(); - $ethntf = $intf->{$ntf_name} ||= { DEVICE => $ntf_name }; - return 'lan_protocol'; + complete => sub { + !$ndiswrapper_do_device_selection->(); }, + post => $ndiswrapper_next_step, }, wireless => diff --git a/perl-install/network/wireless.pm b/perl-install/network/wireless.pm index 000f9717b..564cafb9b 100644 --- a/perl-install/network/wireless.pm +++ b/perl-install/network/wireless.pm @@ -170,29 +170,104 @@ sub wpa_supplicant_add_network { chmod 0600, $wpa_supplicant_conf; } +my $ndiswrapper_prefix = "$::prefix/etc/ndiswrapper"; + sub ndiswrapper_installed_drivers() { - `ndiswrapper -l` =~ /(\w+)\s+driver present/mg; + grep { -d "$ndiswrapper_prefix/$_" } all($ndiswrapper_prefix); +} + +sub ndiswrapper_present_devices { + my ($driver) = @_; + my @supported_devices; + foreach (all("$ndiswrapper_prefix/$driver")) { + my ($ids) = /^([0-9A-Z]{4}:[0-9A-Z]{4})\.[05]\.conf$/; + $ids and push @supported_devices, $ids; + } + grep { member(uc(sprintf("%04x:%04x", $_->{vendor}, $_->{id})), @supported_devices) } detect_devices::probeall(); } -sub ndiswrapper_available_drivers() { - `ndiswrapper -l` =~ /(\w+)\s+driver present, hardware present/mg; +sub ndiswrapper_get_devices { + my ($in, $driver) = @_; + my @devices = ndiswrapper_present_devices($driver); + @devices or $in->ask_warn(N("Error"), N("No device supporting the %s ndiswrapper driver is present!", $driver)); + @devices; } -sub ndiswrapper_setup() { +sub ndiswrapper_ask_driver { + my ($in) = @_; + if (my $inf_file = $in->ask_file(N("Please select the Windows driver (.inf file)"), "/mnt/cdrom")) { + my $driver = basename(lc($inf_file)); + $driver =~ s/\.inf$//; + + #- first uninstall the driver if present, may solve issues if it is corrupted + -d "$ndiswrapper_prefix/$driver" and system('ndiswrapper', '-e', $driver); + + unless (system('ndiswrapper', '-i', $inf_file) == 0) { + $in->ask_warn(N("Error"), N("Unable to install the %s ndiswrapper driver!", $driver)); + return undef; + } + + return $driver; + } + undef; +} + +sub ndiswrapper_find_matching_devices { + my ($device) = @_; + my $net_path = '/sys/class/net'; + my @devices; + + foreach my $interface (all($net_path)) { + my $dev_path = "$net_path/$interface/device"; + -l $dev_path or next; + + my %map = (vendor => 'vendor', device => 'id'); + if (every { hex(chomp_(cat_("$dev_path/$_"))) eq $device->{$map{$_}} } keys %map) { + my $driver = readlink("$net_path/$interface/driver"); + $driver =~ s!.*/!!; + push @devices, [ $interface, $driver ]; + } + } + + @devices; +} + +sub ndiswrapper_find_conflicting_devices { + my ($device) = @_; + grep { $_->[1] ne "ndiswrapper" } ndiswrapper_find_matching_devices($device); +} + +sub ndiswrapper_find_interface { + my ($device) = @_; + my $dev = find { $_->[1] eq "ndiswrapper" } ndiswrapper_find_matching_devices($device); + $dev->[0]; +} + +sub ndiswrapper_setup_device { + my ($in, $device) = @_; + eval { modules::unload("ndiswrapper") }; #- unload ndiswrapper first so that the newly installed .inf files will be read eval { modules::load("ndiswrapper") }; - #- FIXME: move this somewhere in get_eth_cards, so that configure_eth_aliases correctly writes ndiswrapper - #- find the first interface matching an ndiswrapper driver, try ethtool then sysfs - my @available_drivers = ndiswrapper_available_drivers(); - my $ntf_name = find { - my $drv = c::getNetDriver($_) || readlink("/sys/class/net/$_/driver"); - $drv =~ s!.*/!!; - member($drv, @available_drivers); - } detect_devices::getNet(); - #- fallback on wlan0 - return $ntf_name || "wlan0"; + if ($@) { + $in->ask_warn(N("Error"), N("Unable to load the ndiswrapper module!")); + return; + } + + my @ndiswrapper_conflicts = ndiswrapper_find_conflicting_devices($device); + if (@ndiswrapper_conflicts) { + $in->ask_yesorno(N("Warning"), N("The selected device has already been configured with the %s driver. +Do you really want to use a ndiswrapper driver ?", $ndiswrapper_conflicts[0][1])) or return; + } + + my $interface = ndiswrapper_find_interface($device); + unless ($interface) { + $in->ask_warn(N("Error"), N("Unable to find the ndiswrapper interface!")); + return; + } + + $interface; } 1; -- cgit v1.2.1