summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--perl-install/network/netconnect.pm111
-rw-r--r--perl-install/network/wireless.pm103
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;