wok rev 1850
Add: tazndis, replacement for ndiswrapper util.
author | Eric Joseph-Alexandre <erjo@slitaz.org> |
---|---|
date | Sun Dec 14 10:53:02 2008 +0100 (2008-12-14) |
parents | ae564d97575d |
children | f9c021d9b2fc |
files | tazndis/receipt tazndis/stuff/tazndis |
line diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/tazndis/receipt Sun Dec 14 10:53:02 2008 +0100 1.3 @@ -0,0 +1,18 @@ 1.4 +# SliTaz package receipt. 1.5 + 1.6 +PACKAGE="tazndis" 1.7 +VERSION="1.53" 1.8 +CATEGORY="networking" 1.9 +SHORT_DESC="ndiswrapper replacement for SliTaz" 1.10 +MAINTAINER="erjo@slitaz.org" 1.11 +DEPENDS="perl-core" 1.12 +TARBALL="$PACKAGE-$VERSION.tar.gz" 1.13 +WEB_SITE="http://www.slitaz.org" 1.14 + 1.15 +# Rules to gen a SliTaz package suitable for Tazpkg. 1.16 +genpkg_rules() 1.17 +{ 1.18 + mkdir -p $fs/usr/bin 1.19 + cp -a stuff/${PACKAGE} $fs/usr/bin 1.20 +} 1.21 +
2.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 2.2 +++ b/tazndis/stuff/tazndis Sun Dec 14 10:53:02 2008 +0100 2.3 @@ -0,0 +1,973 @@ 2.4 +#!/usr/bin/perl 2.5 + 2.6 +#/* 2.7 +#* tazndis, install, remove or list of NDIS drivers. 2.8 +#* 2.9 +#* This program is a replacement for ndiswrapper utility written by 2.10 +#* Pontus Fuchs and Giridhar Pemmasani. 2.11 +#* Most part of code come from the original ndiswrapper PERL script. 2.12 +#* 2.13 +#* If you need more complexe commands consider to use the original ndiswrapper 2.14 +#* instead. 2.15 +#* 2.16 +#* Copyright (C) 2008 Eric Joseph-Alexandre 2.17 +#* Copyright (C) 2005-2006 Pontus Fuchs, Giridhar Pemmasani 2.18 +#* 2.19 +#* 2.20 +#* This program is free software; you can redistribute it and/or modify 2.21 +#* it under the terms of the GNU General Public License as published by 2.22 +#* the Free Software Foundation; either version 2 of the License, or 2.23 +#* (at your option) any later version. 2.24 +#* 2.25 +#* This program is distributed in the hope that it will be useful, 2.26 +#* but WITHOUT ANY WARRANTY; without even the implied warranty of 2.27 +#* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 2.28 +#* GNU General Public License for more details. 2.29 +#* 2.30 +#*/ 2.31 + 2.32 +$ENV{PATH} = "/sbin:/usr/sbin:$ENV{PATH}"; 2.33 + 2.34 +my $WRAP_PCI_BUS = 5; 2.35 +my $WRAP_PCMCIA_BUS = 8; 2.36 +my $WRAP_USB_BUS = 15; 2.37 + 2.38 +my %sections; 2.39 +my %parsed_sections; 2.40 +my $confdir = "/etc/ndiswrapper"; 2.41 +my $src_dir; 2.42 +my $driver_name; 2.43 +my @source_disks_files; 2.44 + 2.45 +my $re_dev_id = "([[:xdigit:]]{4})"; 2.46 +my $re_sub_dev_conf = "$re_dev_id:$re_dev_id:$re_dev_id:$re_dev_id" . 2.47 + "\.([[:xdigit:]]+)\.conf"; 2.48 +my $re_dev_conf = "$re_dev_id:$re_dev_id\.([[:xdigit:]]+)\.conf"; 2.49 + 2.50 +# fixup list for parameters. 2.51 +my %param_fixlist = ("EnableRadio|0" => "1", 2.52 + "IBSSGMode|0" => "2", 2.53 + "PrivacyMode|0" => "2", 2.54 + "MapRegisters|256" => "64", 2.55 + "AdhocGMode|1" => "0"); 2.56 + 2.57 +if (@ARGV < 1) { 2.58 + usage(); 2.59 + exit(1); 2.60 +} 2.61 + 2.62 +my $res; 2.63 +my $dbg_file; 2.64 + 2.65 +$dbg_file = "/dev/null"; 2.66 + 2.67 +# "-D" is for development/debugging only 2.68 +if ($ARGV[0] eq "-D") { 2.69 + $dbg_file = "/tmp/ndiswrapper.dbg"; 2.70 + $confdir = "/tmp/ndiswrapper"; 2.71 + open(DBG, "> $dbg_file") or die "couldn't open $dbg_file: $!"; 2.72 + shift; 2.73 +} 2.74 + 2.75 +if ($ARGV[0] eq "-i" and @ARGV == 2) { 2.76 + $res = install($ARGV[1]); 2.77 +} elsif (($ARGV[0] eq "-r") and @ARGV == 2) { 2.78 + $res = remove_driver($ARGV[1]); 2.79 +} elsif ($ARGV[0] eq "-l" and @ARGV == 1) { 2.80 + $res = list_drivers(); 2.81 +} elsif ($ARGV[0] eq "-v" and @ARGV == 1) { 2.82 + $res = check_version(); 2.83 +} else { 2.84 + usage(); 2.85 +} 2.86 +close(DBG); 2.87 +exit($res); 2.88 + 2.89 +sub usage() { 2.90 + print "install/manage Windows drivers for ndiswrapper\n\n" . 2.91 + "usage: ndiswrapper OPTION\n" . 2.92 + "-i inffile install driver described by 'inffile'\n" . 2.93 + "-r driver remove 'driver'\n" . 2.94 + "-l list installed drivers\n" . 2.95 + "-v report version information\n\n" . 2.96 + "If you need more complex operation, you may use ndiswrapper instead.\n" ; 2.97 +} 2.98 + 2.99 +#/* 2.100 +#* Begin of PERL modules substition 2.101 +#* 2.102 +#* Replaced File.pm 2.103 + 2.104 +sub basename(@_){ 2.105 + $var = $_[0]; 2.106 + $var =~ s#.*/(.*)$#$1#; 2.107 + return $var; 2.108 +} 2.109 + 2.110 +sub dirname { 2.111 + local $var = $_[0]; 2.112 + $var =~ s#(.*)/.*$#$1#; 2.113 + return $var; 2.114 +} 2.115 + 2.116 +# delete given single tree with no sub directories. 2.117 +sub rmtree { 2.118 + local $dir = $_[0]; 2.119 + opendir(DIR, $dir) or die "couldn't delete $dir: $!\n"; 2.120 + @dirs = grep(!/^.{1,2}$/, readdir(DIR)); 2.121 + foreach $file (@dirs){ 2.122 + unlink "$dir/$file" or die "couldn't delete file $file $!"; 2.123 + } 2.124 + if(rmdir "$dir"){ 2.125 + return 1; 2.126 + }else{ 2.127 + return 0; 2.128 + } 2.129 +} 2.130 + 2.131 +# return current path. 2.132 +sub cwd { 2.133 + local $var; 2.134 + chomp($var = `pwd`); 2.135 + return $var; 2.136 +} 2.137 + 2.138 +# 2.139 +sub copy { 2.140 + local ($file1, $file2) = @_; 2.141 + open (F1, "$file1") or 2.142 + die "couldn't open file $file1 for reading $!\n"; 2.143 + open (F2, ">$file2") or 2.144 + die "couldn't open file $file2 for writing $!\n"; 2.145 + if ($file1 =~ /\.((bin)|(sys)|(cat))$/) { 2.146 + binmode F1; 2.147 + binmode F2; 2.148 + while (read(F1,$buffer,1)) { 2.149 + print(F2 $buffer); 2.150 + } 2.151 + } else { 2.152 + while (<F1>) { 2.153 + print F2 $_; 2.154 + } 2.155 + } 2.156 + close F1; 2.157 + close F2; 2.158 +} 2.159 + 2.160 +## 2.161 +## End of PERL modules substition 2.162 +## 2.163 + 2.164 +sub remove_driver { 2.165 + my $driver = shift; 2.166 + if (!rmtree("$confdir/$driver", 0, 1)) { 2.167 + warn "couldn't delete $confdir/$driver: $!\n"; 2.168 + } 2.169 + return 0; 2.170 +} 2.171 + 2.172 +sub abort { 2.173 + remove_driver($driver_name); 2.174 + exit 1; 2.175 +} 2.176 + 2.177 +sub check_version { 2.178 + my ($utils_version, $module_utils_version, $res); 2.179 + $res = 0; 2.180 + $utils_version = `loadndisdriver -v`; 2.181 + chomp($utils_version); 2.182 + $utils_version =~ s/^version: //; 2.183 + if (length($utils_version) eq 0) { 2.184 + printf "utils version is too old!\n"; 2.185 + $res = -1; 2.186 + } 2.187 + $module_utils_version = 0; 2.188 + open(MODINFO, "modinfo ndiswrapper |"); 2.189 + while (my $line = <MODINFO>) { 2.190 + if ($line =~ /utils_version:.*read only:\s([0-9\.]+)/) { 2.191 + $module_utils_version = $1; 2.192 + last; 2.193 + } 2.194 + } 2.195 + if ($module_utils_version eq 0) { 2.196 + printf "module version is too old!\n"; 2.197 + $res = -1; 2.198 + } elsif ($utils_version ne $module_utils_version) { 2.199 + printf "utils version '%s' is incompatible with utils version needed" . 2.200 + " by driver ('%s')!\n", $utils_version, $module_utils_version; 2.201 + $res = -1; 2.202 + } 2.203 + printf "utils version: '%s', utils version needed by module: '%s'\n", 2.204 + $utils_version, $module_utils_version; 2.205 + printf "module details:\n"; 2.206 + system("modinfo ndiswrapper | grep -E '^(version|vermagic|filename)'"); 2.207 + 2.208 + if ($res) { 2.209 + printf "\nYou may need to upgrade driver and/or utils to latest " . 2.210 + "versions available at\n" . 2.211 + "http://ndiswrapper.sourceforge.net\n"; 2.212 + } 2.213 + return $res; 2.214 +} 2.215 + 2.216 +sub install { 2.217 + my $inf = shift; 2.218 + chomp($inf); 2.219 + $src_dir = dirname($inf); 2.220 + $driver_name = lc(basename($inf)); 2.221 + 2.222 + unless ($driver_name =~ s/\.inf$//) { 2.223 + die "install argument must be .inf file\n"; 2.224 + } 2.225 + 2.226 + if (! -d $confdir) { 2.227 + mkdir($confdir) or die "couldn't create $confdir: $!"; 2.228 + } 2.229 + (-d "$confdir/$driver_name") and 2.230 + die "driver $driver_name is already installed\n"; 2.231 + 2.232 + read_sections($inf); 2.233 + parse_section("Strings"); 2.234 + parse_section("Version"); 2.235 + parse_source_disks_files(); 2.236 + mkdir("$confdir/$driver_name") or 2.237 + die "couldn't create $confdir/$driver_name: $!"; 2.238 + print "installing $driver_name ...\n"; 2.239 + parse_mfr(); 2.240 + copy_file(basename($inf), basename($inf)); 2.241 + create_fuzzy_conf($driver_name); 2.242 + return 0; 2.243 +} 2.244 + 2.245 +# return lines in section 2.246 +sub get_section { 2.247 + my $name = shift; 2.248 + foreach my $key (keys %sections) { 2.249 + if (lc($key) eq lc($name)) { 2.250 + printf DBG "section: $key\n"; 2.251 + return \@{$sections{$key}}; 2.252 + } 2.253 + } 2.254 + printf DBG "couldn't find section \"$name\"\n"; 2.255 + return 0; 2.256 +} 2.257 + 2.258 +# load inf and split into different sections. 2.259 +sub read_sections { 2.260 + my $filename = shift; 2.261 + open(INF, $filename) or die "couldn't open $filename: $!"; 2.262 + 2.263 + my $name = "none"; 2.264 + @{$sections{$name}} = (); 2.265 + while (my $line = <INF>) { 2.266 + # convert from unicode 2.267 + $line =~ s/\xff\xfe//; 2.268 + $line =~ s/\0//g; 2.269 + 2.270 + chomp($line); 2.271 + $line = trim($line); 2.272 + next if ($line =~ /^$/); 2.273 + if ($line =~ /^\[(.+)\]/) { 2.274 + $name = $1; 2.275 + @{$sections{$name}} = (); 2.276 + } else { 2.277 + push(@{$sections{$name}}, $line); 2.278 + } 2.279 + } 2.280 + close(INF); 2.281 + foreach $name (keys %sections) { 2.282 + printf DBG "section: %s\n", $name; 2.283 + foreach my $line (@{$sections{$name}}) { 2.284 + printf DBG "%s: %s\n", $name, $line; 2.285 + } 2.286 + } 2.287 +} 2.288 + 2.289 +sub parse_section { 2.290 + my $name = shift; 2.291 + my $lines = get_section($name); 2.292 + if (!$lines) { 2.293 + return; 2.294 + } 2.295 + $parsed_sections{$name} = (); 2.296 + foreach my $line (@{$lines}) { 2.297 + (my $key, my $val) = parse_key_value($line); 2.298 + if ($key) { 2.299 + $val = strip_quotes($val); 2.300 + $parsed_sections{$name}->{$key} = $val; 2.301 + printf DBG "$name: %s = %s\n", $key, $val; 2.302 + } 2.303 + } 2.304 +} 2.305 + 2.306 +sub parse_mfr() { 2.307 + my $lines = get_section("Manufacturer"); 2.308 + $lines or die "couldn't get manufacturer section - " . 2.309 + "installation may be incomplete\n"; 2.310 + foreach my $line (@{$lines}) { 2.311 + my ($strkey, $val) = parse_key_value($line); 2.312 + if ($strkey) { 2.313 + my ($models, @targets) = split(",", $val); 2.314 + if ($models) { 2.315 + printf DBG "mfr: %s, %s\n", $line, $models; 2.316 + my $target = choose_target_os(@targets); 2.317 + printf DBG "target: '%s'\n", $target; 2.318 + parse_models($models, $target); 2.319 + } 2.320 + } 2.321 + } 2.322 +} 2.323 + 2.324 +sub parse_models { 2.325 + my ($models, $target) = @_; 2.326 + printf DBG "models: target: '%s'.'%s'\n", $models, $target; 2.327 + my $lines = get_target_os_section($models, $target); 2.328 + if (!$lines) { 2.329 + warn "couldn't find models section \"$models\" -\n" . 2.330 + "installation may be incomplete\n"; 2.331 + return -1; 2.332 + } 2.333 + foreach my $line (@{$lines}) { 2.334 + $line = del_comment($line); 2.335 + next if (length($line) eq 0); 2.336 + (my $dev_desc, my $val) = parse_key_value($line); 2.337 + my @fields = split(",", $val); 2.338 + if (@fields le 1) { 2.339 + printf "couldn't find install directive: %s\n", $line; 2.340 + next; 2.341 + } 2.342 + my $section = trim($fields[0]); 2.343 + my $hwid = trim($fields[1]); 2.344 + if ($hwid =~ /^%.+%$/) { 2.345 + $hwid = get_string_value($hwid); 2.346 + } 2.347 + # TODO: deal with compatible IDs as hwid? 2.348 + my ($bus_type, $vendor, $device, $subvendor, $subdevice) = 2.349 + parse_hwid($hwid); 2.350 + next if (!$vendor); 2.351 + printf DBG "models: %s, %s, %s\n", $section, $hwid, $vendor; 2.352 + parse_install($section, $target, $bus_type, $vendor, $device, 2.353 + $subvendor, $subdevice); 2.354 + } 2.355 +} 2.356 + 2.357 +sub parse_install { 2.358 + my ($section, $target, $bus_type, $vendor, $device, 2.359 + $subvendor, $subdevice) = @_; 2.360 + my $lines = get_target_os_section($section, $target); 2.361 + if (!$lines) { 2.362 + warn "couldn't find install section \"$section\" -\n" . 2.363 + "installation may be incomplete\n"; 2.364 + return -1; 2.365 + } 2.366 + 2.367 + my $filename = "$vendor:$device"; 2.368 + if ($subvendor) { 2.369 + $filename .= ":$subvendor:$subdevice" 2.370 + } 2.371 + $filename .= sprintf(".%X.conf", $bus_type); 2.372 + 2.373 + my (@addregs, @copyfiles); 2.374 + foreach my $line (@{$lines}) { 2.375 + $line =~ s/^;\s*//; 2.376 + $line = trim(del_comment($line)); 2.377 + my ($key, $val) = parse_key_value($line); 2.378 + my @array; 2.379 + if ($key) { 2.380 + if (lc($key) eq "addreg") { 2.381 + @array = split(",", $val); 2.382 + foreach my $reg (@array) { 2.383 + push @addregs, trim($reg); 2.384 + } 2.385 + } elsif (lc($key) eq "copyfiles") { 2.386 + printf DBG "copyfiles: %s\n", $val; 2.387 + @array = split(",", $val); 2.388 + foreach my $copy_file_dirs (@array) { 2.389 + my @copy_sec = split(",", $copy_file_dirs); 2.390 + foreach my $file (@copy_sec) { 2.391 + push @copyfiles, trim($file); 2.392 + } 2.393 + } 2.394 + } elsif (lc($key) eq "bustype") { 2.395 + printf DBG "bustype: %s\n", $val; 2.396 + $bus_type = $val; 2.397 + } 2.398 + } 2.399 + } 2.400 + 2.401 + open(CONF, ">$confdir/$driver_name/$filename") or 2.402 + die "couldn't create file $confdir/$driver_name/$filename: $!"; 2.403 + 2.404 + printf CONF "sys_files|"; 2.405 + foreach my $file (@copyfiles) { 2.406 + parse_copy_file($file); 2.407 + } 2.408 + printf CONF "\n"; 2.409 + 2.410 + my $version = get_section_value("Version", "DriverVer"); 2.411 + my $provider = get_section_value("Version", "Provider"); 2.412 + my $classguid = get_section_value("Version", "ClassGUID"); 2.413 + my $providerstring = trim(strip_quotes(get_string_value(trim($provider)))); 2.414 + $classguid =~ s/^\s*{//; 2.415 + $classguid =~ s/}\s*$//; 2.416 + 2.417 + printf CONF "NdisVersion|0x50001\n"; 2.418 + printf CONF "Environment|1\n"; 2.419 + printf CONF "class_guid|%s\n", $classguid; 2.420 + printf CONF "driver_version|%s,%s\n", $providerstring, $version; 2.421 + printf CONF "BusType|%s\n", $bus_type; 2.422 + printf CONF "SlotNumber|01\n"; 2.423 + printf CONF "NetCfgInstanceId|{28022A01-1234-5678-ABCDE-123813291A00}\n"; 2.424 + printf CONF "\n"; 2.425 + close(CONF); 2.426 + 2.427 + open(CONF, "|sort|uniq >>$confdir/$driver_name/$filename") or 2.428 + die "couldn't create file $confdir/$driver_name/$filename: $!"; 2.429 + 2.430 + foreach my $reg (@addregs) { 2.431 + parse_registry($reg); 2.432 + } 2.433 + close(CONF); 2.434 +} 2.435 + 2.436 +sub parse_registry { 2.437 + my ($reg, $conf) = @_; 2.438 + my $lines = get_section($reg); 2.439 + if (!$lines) { 2.440 + warn "couldn't find section \"$reg\" -\n" . 2.441 + "installation may be incomplete\n"; 2.442 + return -1; 2.443 + } 2.444 + 2.445 + my $driver_desc = 0; 2.446 + foreach my $line (@{$lines}) { 2.447 + $line = del_comment($line); 2.448 + my @fields = split(",", $line); 2.449 + next if (@fields lt 4); 2.450 + my $value; 2.451 + my $param = trim($fields[1]); 2.452 + if ($param =~ /^ndi\\/i) { 2.453 + if ($param =~ /^ndi\\params\\(.+)/i) { 2.454 + $param = strip_quotes(trim($1)); 2.455 + $param =~ s/\\.*$//; 2.456 + next if (lc(trim($fields[2])) ne "default"); 2.457 + $value = strip_quotes(trim($fields[4])); 2.458 + } else { 2.459 + printf DBG "ignoring parameter $line\n"; 2.460 + next; 2.461 + } 2.462 + } else { 2.463 + $param = strip_quotes(trim($fields[2])); 2.464 + next if (length($param) eq 0); 2.465 + $value = strip_quotes(trim($fields[4])); 2.466 + } 2.467 + $value = get_string_value($value); 2.468 + if (length($param) gt 0) { 2.469 + if ($param_fixlist{"$param|$value"}) { 2.470 + my $orig_value = $value; 2.471 + $value = $param_fixlist{"$param|$value"}; 2.472 + printf "forcing parameter $param from $orig_value to $value\n"; 2.473 + } 2.474 + printf CONF "%s|%s\n", $param, $value; 2.475 + if ($param =~ /^DriverDesc$/) { 2.476 + $driver_desc = 1; 2.477 + } 2.478 + } 2.479 + } 2.480 + if ($driver_desc == 0) { 2.481 + printf CONF "DriverDesc|NDIS Network Adapter\n"; 2.482 + } 2.483 +} 2.484 + 2.485 +sub parse_copy_file { 2.486 + my $copy_name = shift; 2.487 + 2.488 + if ($copy_name =~ /^\@/) { 2.489 + $copy_name =~ s/^\@//; 2.490 + $copy_name = trim($copy_name); 2.491 + if (valid_copy_file_name($copy_name)) { 2.492 + return copy_file($copy_name, $copy_name); 2.493 + } 2.494 + } 2.495 + 2.496 + my $lines = get_section($copy_name); 2.497 + if (!$lines) { 2.498 + warn "couldn't find section \"$copy_name\" -\n" . 2.499 + "installation may be incomplete\n"; 2.500 + return -1; 2.501 + } 2.502 + foreach my $line (@{$lines}) { 2.503 + $line = trim($line); 2.504 + 2.505 + # some inf files have file names commented out; get file names from them 2.506 + $line =~ s/^\s*;//; 2.507 + my @files = split(",", $line); 2.508 + if (@files == 0) { 2.509 + printf DBG "copyfiles section $copy_name has no files\n"; 2.510 + return -1; 2.511 + } 2.512 + my $src, my $dst; 2.513 + if (@files > 1 and length(trim($files[1])) > 0) { 2.514 + $src = $files[1]; 2.515 + if (length(trim($files[0])) > 0) { 2.516 + $dst = $files[0]; 2.517 + } else { 2.518 + $dst = $src; 2.519 + } 2.520 + } else { 2.521 + $src = $files[0]; 2.522 + $dst = $src; 2.523 + } 2.524 + $src =~ s/^.*\\//; 2.525 + $dst =~ s/^.*\\//; 2.526 + printf DBG "src: '%s', dst: '%s'\n", $src, $dst; 2.527 + $src = trim(del_comment($src)); 2.528 + next if (length($src) eq 0); 2.529 + if (valid_copy_file_name($src)) { 2.530 + $dst = trim(del_comment($dst)); 2.531 + printf DBG "src: '%s', dst: '%s'\n", $src, $dst; 2.532 + copy_file($src, $dst); 2.533 + } else { 2.534 + printf DBG "invalid file '%s' ignored\n", $src; 2.535 + } 2.536 + } 2.537 + return 0; 2.538 +} 2.539 + 2.540 +sub parse_hwid { 2.541 + my $hwid = uc(shift); 2.542 + if ($hwid =~ /(PCI\\)?VEN_(\w+)&DEV_(\w+)&SUBSYS_(\w{4})(\S{4})/) { 2.543 + return ($WRAP_PCI_BUS, $2, $3, $4, $5); 2.544 + } elsif ($hwid =~ /(PCI\\)?VEN_(\w+)&DEV_(\w+)/) { 2.545 + return ($WRAP_PCI_BUS, $2, $3, 0, 0); 2.546 + } elsif ($hwid =~ /(USB\\)?VID_(\w+)&PID_(\w+)/) { 2.547 + return ($WRAP_USB_BUS, $2, $3, 0, 0); 2.548 + } else { 2.549 + return 0; 2.550 + } 2.551 +} 2.552 + 2.553 +sub parse_key_value { 2.554 + my $line = shift; 2.555 + 2.556 + $line = del_comment($line); 2.557 + if ($line =~ /([^=]+)=(.+)/) { 2.558 + return (trim($1), trim($2)); 2.559 + } else { 2.560 + return 0; 2.561 + } 2.562 +} 2.563 + 2.564 +sub choose_target_os { 2.565 + my @targets = @_; 2.566 + my $arch = `uname -m`; 2.567 + chomp($arch); 2.568 + printf DBG "arch: %s\n", $arch; 2.569 + if ($arch =~ /64$/) { 2.570 + $arch = "amd64"; 2.571 + } else { 2.572 + $arch = "x86"; 2.573 + } 2.574 + printf DBG "arch: %s\n", $arch; 2.575 + my @prefs = ("NT($arch)\.5\.1", "NT($arch)\.5", "NT($arch)", 2.576 + "NT\.5\.1", "NT\.5", "NT"); 2.577 + foreach my $pref (@prefs) { 2.578 + foreach my $target (@targets) { 2.579 + $target = trim($target); 2.580 + printf DBG "target: '%s', pref: '%s'\n", $target, $pref; 2.581 + if ($target =~ /NT((amd64)|(x86))/i) { 2.582 + printf DBG "target arch: '%s'\n", $1; 2.583 + next if ($1 !~ /$arch/i); 2.584 + } 2.585 + if ($target =~ /$pref/i) { 2.586 + return $target; 2.587 + } 2.588 + } 2.589 + } 2.590 + return ""; 2.591 +} 2.592 + 2.593 +sub get_target_os_section { 2.594 + my ($section, $target) = @_; 2.595 + my $lines; 2.596 + 2.597 + chomp($section); 2.598 + $section =~ s/^\s*"\s*//; 2.599 + $section =~ s/\s*"\s*$//; 2.600 + printf DBG "section: \"%s\", target: \"%s\"\n", $section, $target; 2.601 + 2.602 + if (length($target) gt 0) { 2.603 + $lines = get_section($section . "." . $target); 2.604 + return $lines if ($lines); 2.605 + } 2.606 + 2.607 + my $arch = `uname -m`; 2.608 + chomp($arch); 2.609 + printf DBG "arch: %s\n", $arch; 2.610 + if ($arch =~ /64$/) { 2.611 + $arch = "AMD64"; 2.612 + } else { 2.613 + $arch = "X86"; 2.614 + } 2.615 + printf DBG "arch: %s\n", $arch; 2.616 + 2.617 + my @prefs = ("NT$arch.5.1", "NT$arch.5", "NT$arch", 2.618 + "NT.5.1", "NT.5", "NT"); 2.619 + foreach my $pref (@prefs) { 2.620 + $lines = get_section($section . "." . $pref); 2.621 + return $lines if ($lines); 2.622 + } 2.623 + $lines = get_section($section); 2.624 + return $lines if ($lines); 2.625 + 2.626 + printf DBG "couldn't find section \"$section\" for \"$arch\"\n"; 2.627 + return 0; 2.628 +} 2.629 + 2.630 +sub get_section_value { 2.631 + (my $section, my $name) = @_; 2.632 + return $parsed_sections{$section}->{$name}; 2.633 +} 2.634 + 2.635 +sub get_string_value { 2.636 + my $key = shift; 2.637 + if ($key =~ /%(.+)%/) { 2.638 + $key = $1; 2.639 + return get_section_value("Strings", $key); 2.640 + } else { 2.641 + return $key; 2.642 + } 2.643 +} 2.644 + 2.645 +sub copy_file { 2.646 + my ($src, $dst) = @_; 2.647 + 2.648 + # ignore files not needed 2.649 + return 0 if (lc($src) =~ /\.((exe)|(dll)|(cpl)|(hlp))$/); 2.650 + my $real_file = get_file($src); 2.651 + if (length($real_file) gt 0) { 2.652 + $dst = lc($dst); 2.653 + printf DBG "copying \"$src_dir/$real_file\" to " . 2.654 + "\"$confdir/$driver_name/$dst\"\n"; 2.655 + copy("$src_dir/$real_file", "$confdir/$driver_name/$dst") or 2.656 + warn "couldn't copy \"$src_dir/$real_file\" to " . 2.657 + "\"$confdir/$driver_name\": $! -\n" . 2.658 + "installation may be incomplete\n"; 2.659 + printf DBG "chmod: $confdir/$driver_name/$dst\n"; 2.660 + chmod(0644, "$confdir/$driver_name/$dst"); 2.661 + if ($dst =~ /\.sys$/) { 2.662 + printf CONF "%s ", $dst; 2.663 + } 2.664 + } else { 2.665 + warn "couldn't find \"$src\" in \"$src_dir\"; make sure " . 2.666 + "all driver files, including .inf, .sys (and any firmware files) " . 2.667 + "are in \"$src_dir\" -\n" . 2.668 + "installation may be incomplete\n"; 2.669 + } 2.670 + } 2.671 + 2.672 + 2.673 +# for conf files with subvendor and subdevice, create conf files with just 2.674 +# vendor and device 2.675 +sub create_fuzzy_conf { 2.676 + my $driver = shift; 2.677 + my $cwd = cwd(); 2.678 + chdir("$confdir/$driver") or die "couldn't chdir to $confdir/$driver: $!"; 2.679 + open(LS, "ls -1 . |") or die "couldn't open $confdir/$driver: $!"; 2.680 + while (my $file = <LS>) { 2.681 + chomp($file); 2.682 + if ($file =~ /$re_sub_dev_conf/) { 2.683 + my $fuzzy_file = "$1:$2.$5.conf"; 2.684 + printf DBG "file: $file, fuzzy file: $fuzzy_file\n"; 2.685 + if (! -e "$confdir/$driver/$fuzzy_file") { 2.686 + symlink("$file", "$fuzzy_file") or 2.687 + warn "couldn't link $confdir/$driver/$file " . 2.688 + "to $confdir/$driver/$fuzzy_file: $!\n"; 2.689 + } 2.690 + } 2.691 + } 2.692 + close(LS); 2.693 + chdir($cwd) or warn "couldn't chdir to $cwd: $!"; 2.694 + return 0; 2.695 +} 2.696 + 2.697 +# find a file in a case-insensitive way. 2.698 +sub get_file { 2.699 + my $file = lc(shift); 2.700 + if (opendir(DIR, "$src_dir")) { 2.701 + my @allfiles = readdir(DIR); 2.702 + foreach my $real_file (@allfiles) { 2.703 + if (lc($real_file) eq $file) { 2.704 + closedir(DIR); 2.705 + return $real_file; 2.706 + } 2.707 + } 2.708 + closedir(DIR); 2.709 + } else { 2.710 + warn "couldn't open \"$src_dir\": $! -\n" . 2.711 + "installation may be incomplete\n"; 2.712 + } 2.713 + return ""; 2.714 +} 2.715 + 2.716 +sub strip_quotes { 2.717 + my $s = shift; 2.718 + $s =~ s/"(.*)"/$1/; 2.719 + return $s; 2.720 +} 2.721 + 2.722 +sub del_comment { 2.723 + my $s = shift; 2.724 + $s =~ s/;.*//; 2.725 + return $s; 2.726 +} 2.727 + 2.728 +# remove whitsepace at front and end. 2.729 +sub trim { 2.730 + my $s = shift; 2.731 + $s =~ s/^\s*//; 2.732 + $s =~ s/\s*$//; 2.733 + return $s; 2.734 +} 2.735 + 2.736 +sub valid_copy_file_name { 2.737 + my $file = shift; 2.738 + $file = lc($file); 2.739 + printf DBG "file name: %s\n", $file; 2.740 + foreach my $disk_file (@source_disks_files) { 2.741 + return 1 if ($file eq $disk_file); 2.742 + } 2.743 + # some inf files may not have SourceDisksFiles section, so use 2.744 + # known file names 2.745 + return 1 if ($file =~ /\.((sys)|(bin)|(out))$/); 2.746 + return 0; 2.747 +} 2.748 + 2.749 +sub parse_source_disks_files { 2.750 + my $lines = get_source_disks_files(); 2.751 + if ($lines) { 2.752 + foreach my $line (@{$lines}) { 2.753 + $line = del_comment($line); 2.754 + next if (length($line) eq 0); 2.755 + my @file = split("=", $line); 2.756 + next if (@file eq 0 or length($file[0] eq 0)); 2.757 + printf DBG "source disk file: \"%s\"\n", trim($file[0]); 2.758 + push (@source_disks_files, lc(trim($file[0]))); 2.759 + } 2.760 + } else { 2.761 + warn "couldn't find SourceDisksFiles section - " . 2.762 + "continuing anyway...\n"; 2.763 + } 2.764 +} 2.765 + 2.766 +sub get_source_disks_files { 2.767 + my $arch = `uname -m`; 2.768 + chomp($arch); 2.769 + if ($arch =~ /64$/) { 2.770 + $arch = "AMD64"; 2.771 + } else { 2.772 + $arch = "X86"; 2.773 + } 2.774 + 2.775 + my $lines = get_section("SourceDisksFiles." . $arch); 2.776 + return $lines if ($lines); 2.777 + 2.778 + $lines = get_section("SourceDisksFiles"); 2.779 + return $lines if ($lines); 2.780 + 2.781 + return 0; 2.782 +} 2.783 + 2.784 +sub device_driver_alias { 2.785 + my ($devid, $driver) = @_; 2.786 + my $done = 0; 2.787 + 2.788 + $devid = uc($devid); 2.789 + if (!($devid =~ /^$re_dev_id:$re_dev_id$/)) { 2.790 + printf "'$devid' is not a valid device ID\n"; 2.791 + return 1; 2.792 + } 2.793 + open(LS, "ls -1 $confdir/$driver/ |") or 2.794 + die "couldn't open $confdir/$driver: $!"; 2.795 + 2.796 + while (my $f = <LS>) { 2.797 + chomp($f); 2.798 + if ($f =~ /\.([[:xdigit:]]+)\.conf$/) { 2.799 + if (stat("$confdir/$driver/$devid.$1.conf")) { 2.800 + printf "Driver '$driver' is already used for '$devid'\n"; 2.801 + $done = 1; 2.802 + last; 2.803 + } 2.804 + if (symlink("$f", "$confdir/$driver/$devid.$1.conf")) { 2.805 + printf "WARNING: Driver '$driver' will be used for '$devid'\n" . 2.806 + "This is safe _only_ if driver $driver is meant for " . 2.807 + "chip in device $devid\n"; 2.808 + $done = 1; 2.809 + last; 2.810 + } else { 2.811 + warn "couldn't create symlink for \"$f\": $! -\n" . 2.812 + "installation may be incomplete\n"; 2.813 + } 2.814 + } 2.815 + } 2.816 + close(LS); 2.817 + if ($done == 0) { 2.818 + printf "driver '$driver' is not installed (properly)!\n"; 2.819 + return 1; 2.820 + } 2.821 + return 0; 2.822 +} 2.823 + 2.824 +sub list_drivers { 2.825 + my $cards = get_cards(); 2.826 + 2.827 + open(LS, "/bin/ls -1 $confdir|") or die "couldn't open $confdir: $!"; 2.828 + while (my $driver = <LS>) { 2.829 + chomp($driver); 2.830 + if (-e "$confdir/$driver") { 2.831 + printf "%s : %s\n", $driver, install_status($cards, $driver); 2.832 + } 2.833 + } 2.834 + close(LS); 2.835 + return 0; 2.836 +} 2.837 + 2.838 + 2.839 +sub get_cards { 2.840 +#01:00.0 Class 0300: 1002:4c66 (rev 01) 2.841 +# Subsystem: 1043:1732 2.842 + my @cards = (); 2.843 + if (open(LSPCI, "/usr/bin/lspci -vn|")) { 2.844 + my $card; 2.845 + while (my $line = <LSPCI>) { 2.846 + if ($line =~ /^[0-9a-f]+.+\s$re_dev_id:$re_dev_id/) { 2.847 + $card = {vendor => uc($1), device => uc($2)}; 2.848 + printf DBG "card: %s, %s\n", $1, $2; 2.849 + } elsif ($line =~ /.+Subsystem:\s$re_dev_id:$re_dev_id/) { 2.850 + $card->{subvendor} = uc($1); 2.851 + $card->{subdevice} = uc($2); 2.852 + printf DBG "sub: %s, %s\n", $1, $2; 2.853 + push(@cards, $card); 2.854 + } 2.855 + } 2.856 + close(LSPCI); 2.857 + } 2.858 + 2.859 + if (open(LSUSB, "lsusb |")) { 2.860 + my $card; 2.861 + while (my $line = <LSUSB>) { 2.862 + if ($line =~ /.+: ID\s$re_dev_id:$re_dev_id/) { 2.863 + $card = {vendor => uc($1), device => uc($2)}; 2.864 + push(@cards, $card); 2.865 + } 2.866 + } 2.867 + close(LSUSB); 2.868 + } 2.869 + return \@cards; 2.870 +} 2.871 + 2.872 +sub install_status { 2.873 + my ($cards, $driver) = @_; 2.874 + 2.875 + if (!$cards or !$driver) { 2.876 + return; 2.877 + } 2.878 + 2.879 + my ($sys, $conf, $inf); 2.880 + my ($vendor, $device, $subvendor, $subdevice, $busid, $ret); 2.881 + 2.882 + $sys = $conf = $inf = 0; 2.883 + open(LS2, "/bin/ls -1 $confdir/$driver|") or 2.884 + die "couldn't open $confdir/$driver: $!"; 2.885 + while (my $file = <LS2>) { 2.886 + chomp($file); 2.887 + if ($file =~ /\.sys$/) { 2.888 + $sys = 1; 2.889 + } elsif ($file =~ /\.inf$/) { 2.890 + $inf = 1; 2.891 + } elsif ($file =~ /^$re_sub_dev_conf$/) { 2.892 + $busid = hex($5); 2.893 + $conf = 1 if ($busid eq $WRAP_PCI_BUS); 2.894 + } elsif ($file =~ /^$re_dev_conf$/) { 2.895 + $busid = hex($3); 2.896 + $conf = 1 if ($busid eq $WRAP_USB_BUS or $busid eq 0 or 2.897 + $busid eq $WRAP_PCI_BUS); 2.898 + } 2.899 + } 2.900 + close(LS2); 2.901 + printf DBG "status: $sys, $inf, $conf\n"; 2.902 + if ($sys eq 0 or $inf eq 0 or $conf eq 0) { 2.903 + $ret = "invalid driver!"; 2.904 + return $ret; 2.905 + } 2.906 + $ret = "driver installed"; 2.907 + open(LS2, "/bin/ls -1 $confdir/$driver|") or 2.908 + die "couldn't open $confdir/$driver: $!"; 2.909 + 2.910 + while (my $file = <LS2>) { 2.911 + chomp($file); 2.912 + next if ($file !~ /\.conf$/); 2.913 + $conf = 0; 2.914 + if ($file =~ /^$re_sub_dev_conf$/) { 2.915 + ($vendor, $device, $subvendor, $subdevice, $busid) = 2.916 + (uc($1), uc($2), uc($3), uc($4), hex($5)); 2.917 + $conf = 1; 2.918 + foreach my $card (@{$cards}) { 2.919 + if ($card->{vendor} eq $vendor and 2.920 + $card->{device} eq $device and 2.921 + $card->{subvendor} eq $subvendor and 2.922 + $card->{subdevice} eq $subdevice and 2.923 + $busid eq $WRAP_PCI_BUS) { 2.924 + $ret .= "\n\tdevice ($vendor:$device" . 2.925 + ":$subvendor:$subdevice) present"; 2.926 + $conf = 2; 2.927 + last; 2.928 + } 2.929 + } 2.930 + } elsif ($file =~ /^$re_dev_conf/) { 2.931 + ($vendor, $device, $subvendor, $subdevice, $busid) = 2.932 + (uc($1), uc($2), "\\*", "\\*", hex($3)); 2.933 + $conf = 1; 2.934 + foreach my $card (@{$cards}) { 2.935 + if ($card->{vendor} eq $vendor and 2.936 + $card->{device} eq $device and 2.937 + ($busid eq $WRAP_USB_BUS or $busid eq 0 or 2.938 + $busid eq $WRAP_PCI_BUS)) { 2.939 + $ret .= "\n\tdevice ($vendor:$device) present"; 2.940 + $conf = 2; 2.941 + last; 2.942 + } 2.943 + } 2.944 + } 2.945 + next if ($conf le 1); 2.946 + # find if kernel knows of an alternate driver for this device 2.947 + my $devstring; 2.948 + if ($busid eq $WRAP_USB_BUS or $busid eq 0) { 2.949 + $devstring = sprintf("usb:v%sp%sd", $vendor, $device); 2.950 + } elsif ($busid eq $WRAP_PCI_BUS) { 2.951 + $devstring = sprintf("pci:v0000%sd0000%ssv", $vendor, $device); 2.952 + } else { 2.953 + next; 2.954 + } 2.955 + open(MODPROBE, "modprobe -c|") or next; 2.956 + while (my $line = <MODPROBE>) { 2.957 + my $alt; 2.958 + chomp($line); 2.959 + next if $line !~ /$devstring/; 2.960 + $alt = (split(' ', $line))[-1]; 2.961 + chomp($alt); 2.962 + if (length($alt) gt 0 and $alt ne "ndiswrapper") { 2.963 + $ret .= " (alternate driver: $alt)"; 2.964 + last; 2.965 + } 2.966 + } 2.967 + close(MODPROBE); 2.968 + } 2.969 + close(LS2); 2.970 + printf DBG "driver: $driver, $ret\n"; 2.971 + return $ret; 2.972 +} 2.973 + 2.974 +## Local Variables: ## 2.975 +## cperl-indent-level: 4 ## 2.976 +## End: ##