📄 ndiswrapper
字号:
#!/usr/bin/perl#/*#* Copyright (C) 2005-2006 Pontus Fuchs, Giridhar Pemmasani#*#*#* This program is free software; you can redistribute it and/or modify#* it under the terms of the GNU General Public License as published by#* the Free Software Foundation; either version 2 of the License, or#* (at your option) any later version.#*#* This program is distributed in the hope that it will be useful,#* but WITHOUT ANY WARRANTY; without even the implied warranty of#* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the#* GNU General Public License for more details.#*#*/use strict;use Fcntl ':mode';use File::Basename;use File::Copy;use File::Path;use Cwd;$ENV{PATH} = "/sbin:/usr/sbin:$ENV{PATH}";my $WRAP_PCI_BUS = 5;my $WRAP_PCMCIA_BUS = 8;my $WRAP_USB_BUS = 15;my %sections;my %parsed_sections;my $confdir = "/etc/ndiswrapper";my $src_dir;my $driver_name;my $re_dev_id = "([[:xdigit:]]{4})";my $re_sub_dev_conf = "$re_dev_id:$re_dev_id:$re_dev_id:$re_dev_id" . "\.([[:xdigit:]]+)\.conf";my $re_dev_conf = "$re_dev_id:$re_dev_id\.([[:xdigit:]]+)\.conf";# fixup list for parameters.my %param_fixlist = ("EnableRadio|0" => "1", "IBSSGMode|0" => "2", "PrivacyMode|0" => "2", "MapRegisters|256" => "64", "AdhocGMode|1" => "0");if (@ARGV < 1) { usage(); exit(1);}my $modconf;if (`uname -r` =~ /(\d+)\.(\d+)\.(\d+)/) { if ($2 > 4) { if (-d "/etc/modprobe.d") { $modconf = "/etc/modprobe.d/ndiswrapper" } else { $modconf = "/etc/modprobe.conf" } } else { if (-d "/etc/modutils") { $modconf = "/etc/modutils/ndiswrapper"; } else { $modconf = "/etc/modules.conf"; } }}my $res;my $dbg_file;$dbg_file = ">/dev/null";# "-D" is for development/debugging onlyif ($ARGV[0] eq "-D") { $dbg_file = ">/tmp/ndiswrapper.dbg"; $confdir = "/tmp/ndiswrapper"; shift;}open(DBG, $dbg_file) or die "couldn't open $dbg_file: $!";if ($ARGV[0] eq "-i" and @ARGV == 2) { $res = install($ARGV[1]);} elsif (($ARGV[0] eq "-a" or $ARGV[0] eq "-d") and @ARGV == 3) { $res = device_driver_alias($ARGV[1], $ARGV[2]);} elsif (($ARGV[0] eq "-e" or $ARGV[0] eq "-r") and @ARGV == 2) { $res = remove_driver($ARGV[1]);} elsif ($ARGV[0] eq "-l" and @ARGV == 1) { $res = list_drivers();} elsif ($ARGV[0] eq "-m" and @ARGV == 1) { $res = add_module_alias();} elsif ($ARGV[0] eq "-v" and @ARGV == 1) { printf "utils "; system("loadndisdriver -v"); printf "driver "; system("modinfo ndiswrapper | grep -E '^version|^vermagic'"); $res = 0;} elsif ($ARGV[0] eq "-ma" and @ARGV == 1) { $res = generate_module_device_map(0);} elsif ($ARGV[0] eq "-mi" and @ARGV == 1) { $res = generate_module_device_map(1);} else { usage();}close(DBG);exit($res);sub usage() { print "install/manage Windows drivers for ndiswrapper\n\n" . "usage: ndiswrapper OPTION\n" . "-i inffile install driver described by 'inffile'\n" . "-a devid driver use installed 'driver' for 'devid'\n" . "-r driver remove 'driver'\n" . "-l list installed drivers\n" . "-m write configuration for modprobe\n" . "-ma write module alias configuration for all devices\n" . "-mi write module install configuration for all devices\n" . "-v report version information\n\n" . "where 'devid' is either PCIID or USBID of the form XXXX:XXXX,\n" . "as reported by 'lspci -n' or 'lsusb' for the card\n";}sub remove_driver { my $driver = shift; if (!rmtree("$confdir/$driver", 0, 1)) { warn "couldn't delete $confdir/$driver: $!\n"; } return 0;}sub install { my $inf = shift; chomp($inf); $src_dir = dirname($inf); $driver_name = lc(basename($inf)); $driver_name =~ s/\.inf//; if (! -d $confdir) { mkdir($confdir) or die "couldn't create $confdir: $!"; } (-d "$confdir/$driver_name") and die "driver $driver_name is already installed\n"; mkdir("$confdir/$driver_name") or die "couldn't create $confdir/$driver_name: $!"; print "installing $driver_name ...\n"; read_sections($inf); parse_section("Strings"); parse_section("Version"); parse_mfr(); copy_file(basename($inf)); create_fuzzy_conf($driver_name); return 0;}# return lines in sectionsub get_section { my $name = shift; foreach my $key (keys %sections) { if (lc($key) eq lc($name)) { printf DBG "section: $key\n"; return \@{$sections{$key}}; } } printf DBG "couldn't find section \"$name\"\n"; return 0;}# load inf and split into different sections.sub read_sections { my $filename = shift; open(INF, $filename) or die "couldn't open $filename: $!"; my $name = "none"; @{$sections{$name}} = (); while (my $line = <INF>) { # convert from unicode $line =~ s/\xff\xfe//; $line =~ s/\0//g; chomp($line); $line = trim($line); next if ($line =~ /^$/); if ($line =~ /^\[(.+)\]/) { $name = $1; @{$sections{$name}} = (); } else { push(@{$sections{$name}}, $line); } } close(INF); foreach $name (keys %sections) { printf DBG "section: %s\n", $name; foreach my $line (@{$sections{$name}}) { printf DBG "%s: %s\n", $name, $line; } }}sub parse_section { my $name = shift; my $lines = get_section($name); if (!$lines) { return; } $parsed_sections{$name} = (); foreach my $line (@{$lines}) { (my $key, my $val) = parse_key_value($line); if ($key) { $val = strip_quotes($val); $parsed_sections{$name}->{$key} = $val; printf DBG "$name: %s = %s\n", $key, $val; } }}sub parse_mfr() { my $lines = get_section("Manufacturer"); $lines or die "couldn't get manufacturer section - " . "installation may be incomplete\n"; foreach my $line (@{$lines}) { (my $strkey, my $val) = parse_key_value($line); if ($strkey) { (my $models, my @targets) = split(",", $val); if ($models) { printf DBG "mfr: %s, %s\n", $line, $models; parse_models($models); } } }}sub parse_models { my $models = shift; my $lines = get_target_os_section($models); if (!$lines) { warn "couldn't find models section \"$models\" -\n" . "installation may be incomplete\n"; return -1; } foreach my $line (@{$lines}) { $line = del_comment($line); next if (length($line) eq 0); (my $dev_desc, my $val) = parse_key_value($line); my @fields = split(",", $val); if (@fields le 1) { printf "couldn't find install directive: %s\n", $line; next; } my $install_section = trim($fields[0]); my $hwid = trim($fields[1]); if ($hwid =~ /^%.+%$/) { $hwid = get_string_value($hwid); } # TODO: deal with compatible IDs as hwid? (my $bus_type, my $vendor, my $device, my $subvendor, my $subdevice) = parse_hwid($hwid); printf DBG "models: %s, %s\n", $install_section, $hwid, $vendor; next if (!$vendor); parse_install($install_section, $bus_type, $vendor, $device, $subvendor, $subdevice); }}sub parse_install { (my $secn, my $bus_type, my $vendor, my $device, my $subvendor, my $subdevice) = @_; my $lines = get_target_os_section($secn); if (!$lines) { warn "couldn't find install section \"$secn\" -\n" . "installation may be incomplete\n"; return -1; } my $filename = "$vendor:$device"; if ($subvendor) { $filename .= ":$subvendor:$subdevice" } $filename .= sprintf(".%X.conf", $bus_type); my @addregs; my @copyfiles; foreach my $line (@{$lines}) { $line =~ s/^;\s*//; $line = trim(del_comment($line)); (my $key, my $val) = parse_key_value($line); my @array; if ($key) { if (lc($key) eq "addreg") { @array = split(",", $val); foreach my $reg (@array) { push @addregs, trim($reg); } } elsif (lc($key) eq "copyfiles") { printf DBG "copyfiles: %s\n", $val; @array = split(",", $val); foreach my $copy_file (@array) { my @copy_sec = split(",", $copy_file); foreach my $file (@copy_sec) { push @copyfiles, trim($file); } } } elsif (lc($key) eq "bustype") { printf DBG "bustype: %s\n", $val; $bus_type = $val; } } } open(CONF, ">$confdir/$driver_name/$filename") or die "couldn't create file $filename: $!"; my $version = get_section_value("Version", "DriverVer"); my $provider = get_section_value("Version", "Provider"); my $classguid = get_section_value("Version", "ClassGUID"); my $providerstring = trim(strip_quotes(get_string_value(trim($provider)))); $classguid =~ s/^\s*{//; $classguid =~ s/}\s*$//; printf CONF "NdisVersion|0x50001\n"; printf CONF "Environment|1\n"; printf CONF "class_guid|%s\n", $classguid; printf CONF "mac_address|XX:XX:XX:XX:XX:XX\n"; printf CONF "driver_version|%s,%s\n", $providerstring, $version; printf CONF "BusType|%s\n", $bus_type; printf CONF "SlotNumber|01\n"; printf CONF "\n"; close(CONF); open(CONF, "|sort|uniq >>$confdir/$driver_name/$filename") or die "couldn't create file $confdir/$driver_name/$filename: $!"; foreach my $reg (@addregs) { parse_registry($reg); } foreach my $file (@copyfiles) { parse_copy_file($file); } # RTL8185L driver crashes if DriverDesc setting is not found if ($vendor == "10EC" && $device == "8185") { printf CONF "DriverDesc|Realtek RTL8185 54M Wireless LAN Network Adapter\n"; } close(CONF);}sub parse_registry { my $reg = shift; my $conf = shift; my $lines = get_section($reg); if (!$lines) { warn "couldn't find section \"$reg\" -\n" . "installation may be incomplete\n"; return -1; } foreach my $line (@{$lines}) { $line = del_comment($line); my @fields = split(",", $line); next if (@fields lt 4); my $value; my $param = trim($fields[1]); if ($param =~ /^ndi\\/i) { if ($param =~ /^ndi\\params\\(.+)/i) { $param = strip_quotes(trim($1)); $param =~ s/\\.*$//; next if (lc(trim($fields[2])) ne "default"); $value = strip_quotes(trim($fields[4])); } else { printf DBG "ignoring parameter $line\n"; next; } } else { $param = strip_quotes(trim($fields[2])); next if (length($param) eq 0); $value = strip_quotes(trim($fields[4])); } $value = get_string_value($value); if (length($param) gt 0) { if ($param_fixlist{"$param|$value"}) { my $orig_value = $value; $value = $param_fixlist{"$param|$value"}; printf "forcing parameter $param from $orig_value to $value\n"; } printf CONF "%s|%s\n", $param, $value; } }}sub parse_copy_file { my $copy_name = shift; if ($copy_name =~ /^\@/) { $copy_name =~ s/^\@//; return copy_file($copy_name); } my $lines = get_section($copy_name); if (!$lines) { warn "couldn't find section \"$copy_name\" -\n" . "installation may be incomplete\n"; return -1; } foreach my $line (@{$lines}) { $line = trim($line); my @files = split(",", $line); if (@files == 0) { printf DBG "copyfiles section $copy_name has no files\n"; return -1; } my $file; if (@files > 1 and length(trim($files[1])) > 0) { $file = $files[1]; } else { $file = $files[0]; } printf DBG "file: '%s'\n", $file; # some inf files have file names commented out; get file names from them $file =~ s/^\s*;//; # remove (trailing) comment $file = del_comment($file); $file = trim($file); if (length($file) > 0) { if (valid_copy_file_name($file)) { copy_file($file); } else { printf DBG "invalid file '%s' ignored\n", $file; } } } return 0;}sub parse_hwid { my $hwid = uc(shift); if ($hwid =~ /(PCI\\)?VEN_(\w+)&DEV_(\w+)&SUBSYS_(\w{4})(\S{4})/) { return ($WRAP_PCI_BUS, $2, $3, $4, $5); } elsif ($hwid =~ /(PCI\\)?VEN_(\w+)&DEV_(\w+)/) { return ($WRAP_PCI_BUS, $2, $3, 0, 0); } elsif ($hwid =~ /(USB\\)?VID_(\w+)&PID_(\w+)/) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -