rev |
line source |
erjo@1850
|
1 #!/usr/bin/perl
|
erjo@1850
|
2
|
erjo@1850
|
3 #/*
|
erjo@1850
|
4 #* tazndis, install, remove or list of NDIS drivers.
|
erjo@1850
|
5 #*
|
erjo@1850
|
6 #* This program is a replacement for ndiswrapper utility written by
|
erjo@1850
|
7 #* Pontus Fuchs and Giridhar Pemmasani.
|
erjo@1850
|
8 #* Most part of code come from the original ndiswrapper PERL script.
|
erjo@1850
|
9 #*
|
erjo@1850
|
10 #* If you need more complexe commands consider to use the original ndiswrapper
|
erjo@1850
|
11 #* instead.
|
erjo@1850
|
12 #*
|
erjo@1850
|
13 #* Copyright (C) 2008 Eric Joseph-Alexandre
|
erjo@1850
|
14 #* Copyright (C) 2005-2006 Pontus Fuchs, Giridhar Pemmasani
|
erjo@1850
|
15 #*
|
erjo@1850
|
16 #*
|
erjo@1850
|
17 #* This program is free software; you can redistribute it and/or modify
|
erjo@1850
|
18 #* it under the terms of the GNU General Public License as published by
|
erjo@1850
|
19 #* the Free Software Foundation; either version 2 of the License, or
|
erjo@1850
|
20 #* (at your option) any later version.
|
erjo@1850
|
21 #*
|
erjo@1850
|
22 #* This program is distributed in the hope that it will be useful,
|
erjo@1850
|
23 #* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
erjo@1850
|
24 #* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
erjo@1850
|
25 #* GNU General Public License for more details.
|
erjo@1850
|
26 #*
|
erjo@1850
|
27 #*/
|
erjo@1850
|
28
|
erjo@1941
|
29 $VERSION="1.53.1";
|
erjo@1893
|
30 $ENV{PATH} = "/sbin:/usr/sbin:/bin:/usr/bin";
|
erjo@1850
|
31
|
erjo@1850
|
32 my $WRAP_PCI_BUS = 5;
|
erjo@1850
|
33 my $WRAP_PCMCIA_BUS = 8;
|
erjo@1850
|
34 my $WRAP_USB_BUS = 15;
|
erjo@1850
|
35
|
erjo@1850
|
36 my %sections;
|
erjo@1850
|
37 my %parsed_sections;
|
erjo@1850
|
38 my $confdir = "/etc/ndiswrapper";
|
erjo@1850
|
39 my $src_dir;
|
erjo@1850
|
40 my $driver_name;
|
erjo@1850
|
41 my @source_disks_files;
|
erjo@1850
|
42
|
erjo@1850
|
43 my $re_dev_id = "([[:xdigit:]]{4})";
|
erjo@1850
|
44 my $re_sub_dev_conf = "$re_dev_id:$re_dev_id:$re_dev_id:$re_dev_id" .
|
erjo@1850
|
45 "\.([[:xdigit:]]+)\.conf";
|
erjo@1850
|
46 my $re_dev_conf = "$re_dev_id:$re_dev_id\.([[:xdigit:]]+)\.conf";
|
erjo@1850
|
47
|
erjo@1910
|
48 my $rcs_config = "/etc/rcS.conf";
|
erjo@1941
|
49 my $net_config = "/etc/network.conf";
|
erjo@1941
|
50 my $config_change = 1;
|
erjo@1942
|
51 my $dbg = 1;
|
erjo@1941
|
52
|
erjo@1910
|
53
|
erjo@1850
|
54 # fixup list for parameters.
|
erjo@1850
|
55 my %param_fixlist = ("EnableRadio|0" => "1",
|
erjo@1850
|
56 "IBSSGMode|0" => "2",
|
erjo@1850
|
57 "PrivacyMode|0" => "2",
|
erjo@1850
|
58 "MapRegisters|256" => "64",
|
erjo@1850
|
59 "AdhocGMode|1" => "0");
|
erjo@1850
|
60
|
erjo@1850
|
61 if (@ARGV < 1) {
|
erjo@1850
|
62 usage();
|
erjo@1850
|
63 exit(1);
|
erjo@1850
|
64 }
|
erjo@1850
|
65
|
erjo@1850
|
66 my $res;
|
erjo@1850
|
67 my $dbg_file;
|
erjo@1850
|
68
|
erjo@1850
|
69 $dbg_file = "/dev/null";
|
erjo@1850
|
70
|
erjo@1850
|
71 # "-D" is for development/debugging only
|
erjo@1850
|
72 if ($ARGV[0] eq "-D") {
|
erjo@1942
|
73 my $dbg = 0;
|
erjo@1850
|
74 $dbg_file = "/tmp/ndiswrapper.dbg";
|
erjo@1850
|
75 $confdir = "/tmp/ndiswrapper";
|
erjo@1850
|
76 open(DBG, "> $dbg_file") or die "couldn't open $dbg_file: $!";
|
erjo@1850
|
77 shift;
|
erjo@1850
|
78 }
|
erjo@1850
|
79
|
erjo@1850
|
80 if ($ARGV[0] eq "-i" and @ARGV == 2) {
|
erjo@1850
|
81 $res = install($ARGV[1]);
|
erjo@1850
|
82 } elsif (($ARGV[0] eq "-r") and @ARGV == 2) {
|
erjo@1850
|
83 $res = remove_driver($ARGV[1]);
|
erjo@1850
|
84 } elsif ($ARGV[0] eq "-l" and @ARGV == 1) {
|
erjo@1850
|
85 $res = list_drivers();
|
erjo@1850
|
86 } elsif ($ARGV[0] eq "-v" and @ARGV == 1) {
|
erjo@1850
|
87 $res = check_version();
|
erjo@1850
|
88 } else {
|
erjo@1850
|
89 usage();
|
erjo@1850
|
90 }
|
erjo@1850
|
91 close(DBG);
|
erjo@1850
|
92 exit($res);
|
erjo@1850
|
93
|
erjo@1850
|
94 sub usage() {
|
erjo@1893
|
95 print "install/manage Windows drivers for ndiswrapper kernel module\n\n" .
|
erjo@1873
|
96 "usage: tazndis OPTION\n" .
|
erjo@1850
|
97 "-i inffile install driver described by 'inffile'\n" .
|
erjo@1850
|
98 "-r driver remove 'driver'\n" .
|
erjo@1850
|
99 "-l list installed drivers\n" .
|
erjo@1850
|
100 "-v report version information\n\n" .
|
erjo@1893
|
101 "If you need more complex operation, you may install full ndiswrapper package instead.\n" ;
|
erjo@1850
|
102 }
|
erjo@1850
|
103
|
erjo@1850
|
104 #/*
|
erjo@1850
|
105 #* Begin of PERL modules substition
|
erjo@1850
|
106 #*
|
erjo@1850
|
107 #* Replaced File.pm
|
erjo@1850
|
108
|
erjo@1850
|
109 sub basename(@_){
|
erjo@1910
|
110 ($a = shift) =~ s#.*/(.*)$#$1#;
|
erjo@1910
|
111 return $a;
|
erjo@1850
|
112 }
|
erjo@1850
|
113
|
erjo@1850
|
114
|
erjo@1850
|
115 # delete given single tree with no sub directories.
|
erjo@1850
|
116 sub rmtree {
|
erjo@1850
|
117 local $dir = $_[0];
|
erjo@1850
|
118 opendir(DIR, $dir) or die "couldn't delete $dir: $!\n";
|
erjo@1850
|
119 @dirs = grep(!/^.{1,2}$/, readdir(DIR));
|
erjo@1850
|
120 foreach $file (@dirs){
|
erjo@1850
|
121 unlink "$dir/$file" or die "couldn't delete file $file $!";
|
erjo@1850
|
122 }
|
erjo@1850
|
123 if(rmdir "$dir"){
|
erjo@1850
|
124 return 1;
|
erjo@1850
|
125 }else{
|
erjo@1850
|
126 return 0;
|
erjo@1850
|
127 }
|
erjo@1850
|
128 }
|
erjo@1850
|
129
|
erjo@1850
|
130 # return current path.
|
erjo@1850
|
131 sub cwd {
|
erjo@1850
|
132 local $var;
|
erjo@1850
|
133 chomp($var = `pwd`);
|
erjo@1850
|
134 return $var;
|
erjo@1850
|
135 }
|
erjo@1850
|
136
|
erjo@1850
|
137 #
|
erjo@1850
|
138 sub copy {
|
erjo@1850
|
139 local ($file1, $file2) = @_;
|
erjo@1850
|
140 open (F1, "$file1") or
|
erjo@1850
|
141 die "couldn't open file $file1 for reading $!\n";
|
erjo@1850
|
142 open (F2, ">$file2") or
|
erjo@1850
|
143 die "couldn't open file $file2 for writing $!\n";
|
erjo@1850
|
144 if ($file1 =~ /\.((bin)|(sys)|(cat))$/) {
|
erjo@1850
|
145 binmode F1;
|
erjo@1850
|
146 binmode F2;
|
erjo@1850
|
147 while (read(F1,$buffer,1)) {
|
erjo@1850
|
148 print(F2 $buffer);
|
erjo@1850
|
149 }
|
erjo@1850
|
150 } else {
|
erjo@1850
|
151 while (<F1>) {
|
erjo@1850
|
152 print F2 $_;
|
erjo@1850
|
153 }
|
erjo@1850
|
154 }
|
erjo@1850
|
155 close F1;
|
erjo@1850
|
156 close F2;
|
erjo@1850
|
157 }
|
erjo@1850
|
158
|
erjo@1850
|
159 ##
|
erjo@1850
|
160 ## End of PERL modules substition
|
erjo@1850
|
161 ##
|
erjo@1850
|
162
|
erjo@1850
|
163 sub remove_driver {
|
erjo@1850
|
164 my $driver = shift;
|
erjo@1850
|
165 if (!rmtree("$confdir/$driver", 0, 1)) {
|
erjo@1850
|
166 warn "couldn't delete $confdir/$driver: $!\n";
|
erjo@1850
|
167 }
|
erjo@1850
|
168 return 0;
|
erjo@1850
|
169 }
|
erjo@1850
|
170
|
erjo@1850
|
171 sub abort {
|
erjo@1850
|
172 remove_driver($driver_name);
|
erjo@1850
|
173 exit 1;
|
erjo@1850
|
174 }
|
erjo@1850
|
175
|
erjo@1850
|
176 sub check_version {
|
erjo@1850
|
177 my ($utils_version, $module_utils_version, $res);
|
erjo@1850
|
178 $res = 0;
|
erjo@1850
|
179 $utils_version = `loadndisdriver -v`;
|
erjo@1850
|
180 chomp($utils_version);
|
erjo@1850
|
181 $utils_version =~ s/^version: //;
|
erjo@1850
|
182 if (length($utils_version) eq 0) {
|
erjo@1850
|
183 printf "utils version is too old!\n";
|
erjo@1850
|
184 $res = -1;
|
erjo@1850
|
185 }
|
erjo@1850
|
186 $module_utils_version = 0;
|
erjo@1850
|
187 open(MODINFO, "modinfo ndiswrapper |");
|
erjo@1850
|
188 while (my $line = <MODINFO>) {
|
erjo@1850
|
189 if ($line =~ /utils_version:.*read only:\s([0-9\.]+)/) {
|
erjo@1850
|
190 $module_utils_version = $1;
|
erjo@1850
|
191 last;
|
erjo@1850
|
192 }
|
erjo@1850
|
193 }
|
erjo@1850
|
194 if ($module_utils_version eq 0) {
|
erjo@1850
|
195 printf "module version is too old!\n";
|
erjo@1850
|
196 $res = -1;
|
erjo@1850
|
197 } elsif ($utils_version ne $module_utils_version) {
|
erjo@1850
|
198 printf "utils version '%s' is incompatible with utils version needed" .
|
erjo@1850
|
199 " by driver ('%s')!\n", $utils_version, $module_utils_version;
|
erjo@1850
|
200 $res = -1;
|
erjo@1850
|
201 }
|
erjo@1941
|
202 printf "tazndis version: %s\n ", $VERSION;
|
erjo@1850
|
203 printf "utils version: '%s', utils version needed by module: '%s'\n",
|
erjo@1850
|
204 $utils_version, $module_utils_version;
|
erjo@1850
|
205 printf "module details:\n";
|
erjo@1850
|
206 system("modinfo ndiswrapper | grep -E '^(version|vermagic|filename)'");
|
erjo@1850
|
207
|
erjo@1850
|
208 if ($res) {
|
erjo@1850
|
209 printf "\nYou may need to upgrade driver and/or utils to latest " .
|
erjo@1850
|
210 "versions available at\n" .
|
erjo@1850
|
211 "http://ndiswrapper.sourceforge.net\n";
|
erjo@1850
|
212 }
|
erjo@1850
|
213 return $res;
|
erjo@1850
|
214 }
|
erjo@1850
|
215
|
erjo@1910
|
216 sub set_rcs_config {
|
erjo@1910
|
217 # Add ndiswrapper to LOAD_MODULES if needed.
|
erjo@1941
|
218 open (CONFIG, "< $rcs_config") or die "couldn't open $rcs_config:$!";
|
erjo@1941
|
219 open (CONFIG1, "> $rcs_config.tmp") or die "couldn't open $rcs_config.tmp for writting:$!";
|
erjo@1941
|
220 LINE: while(<CONFIG>){
|
erjo@1910
|
221 if(/^LOAD_MODULES/){
|
erjo@1910
|
222 if (!/^LOAD_MODULES=.*ndiswrapper/){
|
erjo@1910
|
223 print "Add ndiswrapper to module list...\n";
|
erjo@1910
|
224 $_ =~ s/(.*)\"$/$1 ndiswrapper\"/;
|
erjo@1941
|
225 $file_change = 0;
|
erjo@1910
|
226 }
|
erjo@1910
|
227 }
|
erjo@1910
|
228 chomp;
|
erjo@1941
|
229 print CONFIG1 "$_\n";
|
erjo@1910
|
230 }
|
erjo@1941
|
231 close CONFIG, CONFIG1;
|
erjo@1910
|
232
|
erjo@1941
|
233 if($file_change == 0){
|
erjo@1910
|
234 rename "$rcs_config.tmp","$rcs_config" or die "couldn't update $rcs_config: $!";
|
erjo@1941
|
235 $config_change=1;
|
erjo@1910
|
236 } else {
|
erjo@1910
|
237 unlink "$rcs_config.tmp";
|
erjo@1910
|
238 }
|
erjo@1941
|
239 }
|
erjo@1941
|
240
|
erjo@1941
|
241 sub set_net_config {
|
erjo@1941
|
242 #
|
erjo@1941
|
243 open (CONFIG, "< $net_config") or die "couldn't open $net_config:$!";
|
erjo@1941
|
244 open (CONFIG1, "> $net_config.tmp") or die "couldn't open $net_config.tmp for writting:$!";
|
erjo@1941
|
245 print "Set WiFi to start at boot time...\n";
|
erjo@1941
|
246 LINE: while(<CONFIG>){
|
erjo@1941
|
247 if(/^WIFI=/){
|
erjo@1941
|
248 if (/^WIFI="no"$/){
|
erjo@1941
|
249 $_ =~ s/^WIFI="no"$/WIFI="yes"/;
|
erjo@1941
|
250 $config_change = 0;
|
erjo@1941
|
251 }
|
erjo@1941
|
252 }
|
erjo@1941
|
253 chomp;
|
erjo@1941
|
254 print CONFIG1 "$_\n";
|
erjo@1941
|
255 }
|
erjo@1941
|
256 close CONFIG, CONFIG1;
|
erjo@1910
|
257
|
erjo@1941
|
258 if($rcs_config_change == 0){
|
erjo@1941
|
259 rename "$net_config.tmp","$net_config" or die "couldn't update $rcs_config: $!";
|
erjo@1941
|
260 $config_change=1;
|
erjo@1941
|
261 } else {
|
erjo@1941
|
262 unlink "$net_config.tmp";
|
erjo@1941
|
263 }
|
erjo@1910
|
264 }
|
erjo@1910
|
265
|
erjo@1910
|
266 sub load_ndiswrapper {
|
erjo@1910
|
267 open (LSMOD, " lsmod |") or die "couldn't get loaded module list: $!";
|
erjo@1941
|
268 if(!/^ndiswrapper/){
|
erjo@1941
|
269 print "Loading ndiswrapper...\n";
|
erjo@1941
|
270 `modprobe ndiswrapper`;
|
erjo@1941
|
271 }
|
erjo@1910
|
272 }
|
erjo@1910
|
273
|
erjo@1850
|
274 sub install {
|
erjo@1850
|
275 my $inf = shift;
|
erjo@1850
|
276 chomp($inf);
|
erjo@1893
|
277 chop($src_dir = `dirname $inf`);
|
erjo@1850
|
278 $driver_name = lc(basename($inf));
|
erjo@1850
|
279
|
erjo@1850
|
280 unless ($driver_name =~ s/\.inf$//) {
|
erjo@1850
|
281 die "install argument must be .inf file\n";
|
erjo@1850
|
282 }
|
erjo@1850
|
283
|
erjo@1850
|
284 if (! -d $confdir) {
|
erjo@1850
|
285 mkdir($confdir) or die "couldn't create $confdir: $!";
|
erjo@1850
|
286 }
|
erjo@1850
|
287 (-d "$confdir/$driver_name") and
|
erjo@1850
|
288 die "driver $driver_name is already installed\n";
|
erjo@1850
|
289
|
erjo@1850
|
290 read_sections($inf);
|
erjo@1850
|
291 parse_section("Strings");
|
erjo@1850
|
292 parse_section("Version");
|
erjo@1850
|
293 parse_source_disks_files();
|
erjo@1850
|
294 mkdir("$confdir/$driver_name") or
|
erjo@1850
|
295 die "couldn't create $confdir/$driver_name: $!";
|
erjo@1850
|
296 print "installing $driver_name ...\n";
|
erjo@1850
|
297 parse_mfr();
|
erjo@1850
|
298 copy_file(basename($inf), basename($inf));
|
erjo@1850
|
299 create_fuzzy_conf($driver_name);
|
erjo@1910
|
300
|
erjo@1910
|
301 #Update LOAD_MODULES and load ndiswrapper.
|
erjo@1942
|
302 # Only if we are not in debug mode.
|
erjo@1942
|
303 if (!$dbg) {
|
erjo@1942
|
304 set_rcs_config();
|
erjo@1942
|
305 load_ndiswrapper();
|
erjo@1942
|
306
|
erjo@1942
|
307 # Ask for WiFi at boot time.
|
erjo@1942
|
308 print "Would you to start WiFi at boot time [y/N]? ";
|
erjo@1942
|
309 chomp(my $answer = <STDIN>);
|
erjo@1942
|
310 if (lc($answer) eq "y") {
|
erjo@1942
|
311 set_net_config();
|
erjo@1942
|
312 }
|
erjo@1941
|
313 }
|
erjo@1893
|
314
|
erjo@1850
|
315 return 0;
|
erjo@1850
|
316 }
|
erjo@1850
|
317
|
erjo@1850
|
318 # return lines in section
|
erjo@1850
|
319 sub get_section {
|
erjo@1850
|
320 my $name = shift;
|
erjo@1850
|
321 foreach my $key (keys %sections) {
|
erjo@1850
|
322 if (lc($key) eq lc($name)) {
|
erjo@1850
|
323 printf DBG "section: $key\n";
|
erjo@1850
|
324 return \@{$sections{$key}};
|
erjo@1850
|
325 }
|
erjo@1850
|
326 }
|
erjo@1850
|
327 printf DBG "couldn't find section \"$name\"\n";
|
erjo@1850
|
328 return 0;
|
erjo@1850
|
329 }
|
erjo@1850
|
330
|
erjo@1850
|
331 # load inf and split into different sections.
|
erjo@1850
|
332 sub read_sections {
|
erjo@1850
|
333 my $filename = shift;
|
erjo@1850
|
334 open(INF, $filename) or die "couldn't open $filename: $!";
|
erjo@1850
|
335
|
erjo@1850
|
336 my $name = "none";
|
erjo@1850
|
337 @{$sections{$name}} = ();
|
erjo@1850
|
338 while (my $line = <INF>) {
|
erjo@1850
|
339 # convert from unicode
|
erjo@1850
|
340 $line =~ s/\xff\xfe//;
|
erjo@1850
|
341 $line =~ s/\0//g;
|
erjo@1850
|
342
|
erjo@1850
|
343 chomp($line);
|
erjo@1850
|
344 $line = trim($line);
|
erjo@1850
|
345 next if ($line =~ /^$/);
|
erjo@1850
|
346 if ($line =~ /^\[(.+)\]/) {
|
erjo@1850
|
347 $name = $1;
|
erjo@1850
|
348 @{$sections{$name}} = ();
|
erjo@1850
|
349 } else {
|
erjo@1850
|
350 push(@{$sections{$name}}, $line);
|
erjo@1850
|
351 }
|
erjo@1850
|
352 }
|
erjo@1850
|
353 close(INF);
|
erjo@1850
|
354 foreach $name (keys %sections) {
|
erjo@1850
|
355 printf DBG "section: %s\n", $name;
|
erjo@1850
|
356 foreach my $line (@{$sections{$name}}) {
|
erjo@1850
|
357 printf DBG "%s: %s\n", $name, $line;
|
erjo@1850
|
358 }
|
erjo@1850
|
359 }
|
erjo@1850
|
360 }
|
erjo@1850
|
361
|
erjo@1850
|
362 sub parse_section {
|
erjo@1850
|
363 my $name = shift;
|
erjo@1850
|
364 my $lines = get_section($name);
|
erjo@1850
|
365 if (!$lines) {
|
erjo@1850
|
366 return;
|
erjo@1850
|
367 }
|
erjo@1850
|
368 $parsed_sections{$name} = ();
|
erjo@1850
|
369 foreach my $line (@{$lines}) {
|
erjo@1850
|
370 (my $key, my $val) = parse_key_value($line);
|
erjo@1850
|
371 if ($key) {
|
erjo@1850
|
372 $val = strip_quotes($val);
|
erjo@1850
|
373 $parsed_sections{$name}->{$key} = $val;
|
erjo@1850
|
374 printf DBG "$name: %s = %s\n", $key, $val;
|
erjo@1850
|
375 }
|
erjo@1850
|
376 }
|
erjo@1850
|
377 }
|
erjo@1850
|
378
|
erjo@1850
|
379 sub parse_mfr() {
|
erjo@1850
|
380 my $lines = get_section("Manufacturer");
|
erjo@1850
|
381 $lines or die "couldn't get manufacturer section - " .
|
erjo@1850
|
382 "installation may be incomplete\n";
|
erjo@1850
|
383 foreach my $line (@{$lines}) {
|
erjo@1850
|
384 my ($strkey, $val) = parse_key_value($line);
|
erjo@1850
|
385 if ($strkey) {
|
erjo@1850
|
386 my ($models, @targets) = split(",", $val);
|
erjo@1850
|
387 if ($models) {
|
erjo@1850
|
388 printf DBG "mfr: %s, %s\n", $line, $models;
|
erjo@1850
|
389 my $target = choose_target_os(@targets);
|
erjo@1850
|
390 printf DBG "target: '%s'\n", $target;
|
erjo@1850
|
391 parse_models($models, $target);
|
erjo@1850
|
392 }
|
erjo@1850
|
393 }
|
erjo@1850
|
394 }
|
erjo@1850
|
395 }
|
erjo@1850
|
396
|
erjo@1850
|
397 sub parse_models {
|
erjo@1850
|
398 my ($models, $target) = @_;
|
erjo@1850
|
399 printf DBG "models: target: '%s'.'%s'\n", $models, $target;
|
erjo@1850
|
400 my $lines = get_target_os_section($models, $target);
|
erjo@1850
|
401 if (!$lines) {
|
erjo@1850
|
402 warn "couldn't find models section \"$models\" -\n" .
|
erjo@1850
|
403 "installation may be incomplete\n";
|
erjo@1850
|
404 return -1;
|
erjo@1850
|
405 }
|
erjo@1850
|
406 foreach my $line (@{$lines}) {
|
erjo@1850
|
407 $line = del_comment($line);
|
erjo@1850
|
408 next if (length($line) eq 0);
|
erjo@1850
|
409 (my $dev_desc, my $val) = parse_key_value($line);
|
erjo@1850
|
410 my @fields = split(",", $val);
|
erjo@1850
|
411 if (@fields le 1) {
|
erjo@1850
|
412 printf "couldn't find install directive: %s\n", $line;
|
erjo@1850
|
413 next;
|
erjo@1850
|
414 }
|
erjo@1850
|
415 my $section = trim($fields[0]);
|
erjo@1850
|
416 my $hwid = trim($fields[1]);
|
erjo@1850
|
417 if ($hwid =~ /^%.+%$/) {
|
erjo@1850
|
418 $hwid = get_string_value($hwid);
|
erjo@1850
|
419 }
|
erjo@1850
|
420 # TODO: deal with compatible IDs as hwid?
|
erjo@1850
|
421 my ($bus_type, $vendor, $device, $subvendor, $subdevice) =
|
erjo@1850
|
422 parse_hwid($hwid);
|
erjo@1850
|
423 next if (!$vendor);
|
erjo@1850
|
424 printf DBG "models: %s, %s, %s\n", $section, $hwid, $vendor;
|
erjo@1850
|
425 parse_install($section, $target, $bus_type, $vendor, $device,
|
erjo@1850
|
426 $subvendor, $subdevice);
|
erjo@1850
|
427 }
|
erjo@1850
|
428 }
|
erjo@1850
|
429
|
erjo@1850
|
430 sub parse_install {
|
erjo@1850
|
431 my ($section, $target, $bus_type, $vendor, $device,
|
erjo@1850
|
432 $subvendor, $subdevice) = @_;
|
erjo@1850
|
433 my $lines = get_target_os_section($section, $target);
|
erjo@1850
|
434 if (!$lines) {
|
erjo@1850
|
435 warn "couldn't find install section \"$section\" -\n" .
|
erjo@1850
|
436 "installation may be incomplete\n";
|
erjo@1850
|
437 return -1;
|
erjo@1850
|
438 }
|
erjo@1850
|
439
|
erjo@1850
|
440 my $filename = "$vendor:$device";
|
erjo@1850
|
441 if ($subvendor) {
|
erjo@1850
|
442 $filename .= ":$subvendor:$subdevice"
|
erjo@1850
|
443 }
|
erjo@1850
|
444 $filename .= sprintf(".%X.conf", $bus_type);
|
erjo@1850
|
445
|
erjo@1850
|
446 my (@addregs, @copyfiles);
|
erjo@1850
|
447 foreach my $line (@{$lines}) {
|
erjo@1850
|
448 $line =~ s/^;\s*//;
|
erjo@1850
|
449 $line = trim(del_comment($line));
|
erjo@1850
|
450 my ($key, $val) = parse_key_value($line);
|
erjo@1850
|
451 my @array;
|
erjo@1850
|
452 if ($key) {
|
erjo@1850
|
453 if (lc($key) eq "addreg") {
|
erjo@1850
|
454 @array = split(",", $val);
|
erjo@1850
|
455 foreach my $reg (@array) {
|
erjo@1850
|
456 push @addregs, trim($reg);
|
erjo@1850
|
457 }
|
erjo@1850
|
458 } elsif (lc($key) eq "copyfiles") {
|
erjo@1850
|
459 printf DBG "copyfiles: %s\n", $val;
|
erjo@1850
|
460 @array = split(",", $val);
|
erjo@1850
|
461 foreach my $copy_file_dirs (@array) {
|
erjo@1850
|
462 my @copy_sec = split(",", $copy_file_dirs);
|
erjo@1850
|
463 foreach my $file (@copy_sec) {
|
erjo@1850
|
464 push @copyfiles, trim($file);
|
erjo@1850
|
465 }
|
erjo@1850
|
466 }
|
erjo@1850
|
467 } elsif (lc($key) eq "bustype") {
|
erjo@1850
|
468 printf DBG "bustype: %s\n", $val;
|
erjo@1850
|
469 $bus_type = $val;
|
erjo@1850
|
470 }
|
erjo@1850
|
471 }
|
erjo@1850
|
472 }
|
erjo@1850
|
473
|
erjo@1850
|
474 open(CONF, ">$confdir/$driver_name/$filename") or
|
erjo@1850
|
475 die "couldn't create file $confdir/$driver_name/$filename: $!";
|
erjo@1850
|
476
|
erjo@1850
|
477 printf CONF "sys_files|";
|
erjo@1850
|
478 foreach my $file (@copyfiles) {
|
erjo@1850
|
479 parse_copy_file($file);
|
erjo@1850
|
480 }
|
erjo@1850
|
481 printf CONF "\n";
|
erjo@1850
|
482
|
erjo@1850
|
483 my $version = get_section_value("Version", "DriverVer");
|
erjo@1850
|
484 my $provider = get_section_value("Version", "Provider");
|
erjo@1850
|
485 my $classguid = get_section_value("Version", "ClassGUID");
|
erjo@1850
|
486 my $providerstring = trim(strip_quotes(get_string_value(trim($provider))));
|
erjo@1850
|
487 $classguid =~ s/^\s*{//;
|
erjo@1850
|
488 $classguid =~ s/}\s*$//;
|
erjo@1850
|
489
|
erjo@1850
|
490 printf CONF "NdisVersion|0x50001\n";
|
erjo@1850
|
491 printf CONF "Environment|1\n";
|
erjo@1850
|
492 printf CONF "class_guid|%s\n", $classguid;
|
erjo@1850
|
493 printf CONF "driver_version|%s,%s\n", $providerstring, $version;
|
erjo@1850
|
494 printf CONF "BusType|%s\n", $bus_type;
|
erjo@1850
|
495 printf CONF "SlotNumber|01\n";
|
erjo@1850
|
496 printf CONF "NetCfgInstanceId|{28022A01-1234-5678-ABCDE-123813291A00}\n";
|
erjo@1850
|
497 printf CONF "\n";
|
erjo@1850
|
498 close(CONF);
|
erjo@1850
|
499
|
erjo@1850
|
500 open(CONF, "|sort|uniq >>$confdir/$driver_name/$filename") or
|
erjo@1850
|
501 die "couldn't create file $confdir/$driver_name/$filename: $!";
|
erjo@1850
|
502
|
erjo@1850
|
503 foreach my $reg (@addregs) {
|
erjo@1850
|
504 parse_registry($reg);
|
erjo@1850
|
505 }
|
erjo@1850
|
506 close(CONF);
|
erjo@1850
|
507 }
|
erjo@1850
|
508
|
erjo@1850
|
509 sub parse_registry {
|
erjo@1850
|
510 my ($reg, $conf) = @_;
|
erjo@1850
|
511 my $lines = get_section($reg);
|
erjo@1850
|
512 if (!$lines) {
|
erjo@1850
|
513 warn "couldn't find section \"$reg\" -\n" .
|
erjo@1850
|
514 "installation may be incomplete\n";
|
erjo@1850
|
515 return -1;
|
erjo@1850
|
516 }
|
erjo@1850
|
517
|
erjo@1850
|
518 my $driver_desc = 0;
|
erjo@1850
|
519 foreach my $line (@{$lines}) {
|
erjo@1850
|
520 $line = del_comment($line);
|
erjo@1850
|
521 my @fields = split(",", $line);
|
erjo@1850
|
522 next if (@fields lt 4);
|
erjo@1850
|
523 my $value;
|
erjo@1850
|
524 my $param = trim($fields[1]);
|
erjo@1850
|
525 if ($param =~ /^ndi\\/i) {
|
erjo@1850
|
526 if ($param =~ /^ndi\\params\\(.+)/i) {
|
erjo@1850
|
527 $param = strip_quotes(trim($1));
|
erjo@1850
|
528 $param =~ s/\\.*$//;
|
erjo@1850
|
529 next if (lc(trim($fields[2])) ne "default");
|
erjo@1850
|
530 $value = strip_quotes(trim($fields[4]));
|
erjo@1850
|
531 } else {
|
erjo@1850
|
532 printf DBG "ignoring parameter $line\n";
|
erjo@1850
|
533 next;
|
erjo@1850
|
534 }
|
erjo@1850
|
535 } else {
|
erjo@1850
|
536 $param = strip_quotes(trim($fields[2]));
|
erjo@1850
|
537 next if (length($param) eq 0);
|
erjo@1850
|
538 $value = strip_quotes(trim($fields[4]));
|
erjo@1850
|
539 }
|
erjo@1850
|
540 $value = get_string_value($value);
|
erjo@1850
|
541 if (length($param) gt 0) {
|
erjo@1850
|
542 if ($param_fixlist{"$param|$value"}) {
|
erjo@1850
|
543 my $orig_value = $value;
|
erjo@1850
|
544 $value = $param_fixlist{"$param|$value"};
|
erjo@1850
|
545 printf "forcing parameter $param from $orig_value to $value\n";
|
erjo@1850
|
546 }
|
erjo@1850
|
547 printf CONF "%s|%s\n", $param, $value;
|
erjo@1850
|
548 if ($param =~ /^DriverDesc$/) {
|
erjo@1850
|
549 $driver_desc = 1;
|
erjo@1850
|
550 }
|
erjo@1850
|
551 }
|
erjo@1850
|
552 }
|
erjo@1850
|
553 if ($driver_desc == 0) {
|
erjo@1850
|
554 printf CONF "DriverDesc|NDIS Network Adapter\n";
|
erjo@1850
|
555 }
|
erjo@1850
|
556 }
|
erjo@1850
|
557
|
erjo@1850
|
558 sub parse_copy_file {
|
erjo@1850
|
559 my $copy_name = shift;
|
erjo@1850
|
560
|
erjo@1850
|
561 if ($copy_name =~ /^\@/) {
|
erjo@1850
|
562 $copy_name =~ s/^\@//;
|
erjo@1850
|
563 $copy_name = trim($copy_name);
|
erjo@1850
|
564 if (valid_copy_file_name($copy_name)) {
|
erjo@1850
|
565 return copy_file($copy_name, $copy_name);
|
erjo@1850
|
566 }
|
erjo@1850
|
567 }
|
erjo@1850
|
568
|
erjo@1850
|
569 my $lines = get_section($copy_name);
|
erjo@1850
|
570 if (!$lines) {
|
erjo@1850
|
571 warn "couldn't find section \"$copy_name\" -\n" .
|
erjo@1850
|
572 "installation may be incomplete\n";
|
erjo@1850
|
573 return -1;
|
erjo@1850
|
574 }
|
erjo@1850
|
575 foreach my $line (@{$lines}) {
|
erjo@1850
|
576 $line = trim($line);
|
erjo@1850
|
577
|
erjo@1850
|
578 # some inf files have file names commented out; get file names from them
|
erjo@1850
|
579 $line =~ s/^\s*;//;
|
erjo@1850
|
580 my @files = split(",", $line);
|
erjo@1850
|
581 if (@files == 0) {
|
erjo@1850
|
582 printf DBG "copyfiles section $copy_name has no files\n";
|
erjo@1850
|
583 return -1;
|
erjo@1850
|
584 }
|
erjo@1850
|
585 my $src, my $dst;
|
erjo@1850
|
586 if (@files > 1 and length(trim($files[1])) > 0) {
|
erjo@1850
|
587 $src = $files[1];
|
erjo@1850
|
588 if (length(trim($files[0])) > 0) {
|
erjo@1850
|
589 $dst = $files[0];
|
erjo@1850
|
590 } else {
|
erjo@1850
|
591 $dst = $src;
|
erjo@1850
|
592 }
|
erjo@1850
|
593 } else {
|
erjo@1850
|
594 $src = $files[0];
|
erjo@1850
|
595 $dst = $src;
|
erjo@1850
|
596 }
|
erjo@1850
|
597 $src =~ s/^.*\\//;
|
erjo@1850
|
598 $dst =~ s/^.*\\//;
|
erjo@1850
|
599 printf DBG "src: '%s', dst: '%s'\n", $src, $dst;
|
erjo@1850
|
600 $src = trim(del_comment($src));
|
erjo@1850
|
601 next if (length($src) eq 0);
|
erjo@1850
|
602 if (valid_copy_file_name($src)) {
|
erjo@1850
|
603 $dst = trim(del_comment($dst));
|
erjo@1850
|
604 printf DBG "src: '%s', dst: '%s'\n", $src, $dst;
|
erjo@1850
|
605 copy_file($src, $dst);
|
erjo@1850
|
606 } else {
|
erjo@1850
|
607 printf DBG "invalid file '%s' ignored\n", $src;
|
erjo@1850
|
608 }
|
erjo@1850
|
609 }
|
erjo@1850
|
610 return 0;
|
erjo@1850
|
611 }
|
erjo@1850
|
612
|
erjo@1850
|
613 sub parse_hwid {
|
erjo@1850
|
614 my $hwid = uc(shift);
|
erjo@1850
|
615 if ($hwid =~ /(PCI\\)?VEN_(\w+)&DEV_(\w+)&SUBSYS_(\w{4})(\S{4})/) {
|
erjo@1850
|
616 return ($WRAP_PCI_BUS, $2, $3, $4, $5);
|
erjo@1850
|
617 } elsif ($hwid =~ /(PCI\\)?VEN_(\w+)&DEV_(\w+)/) {
|
erjo@1850
|
618 return ($WRAP_PCI_BUS, $2, $3, 0, 0);
|
erjo@1850
|
619 } elsif ($hwid =~ /(USB\\)?VID_(\w+)&PID_(\w+)/) {
|
erjo@1850
|
620 return ($WRAP_USB_BUS, $2, $3, 0, 0);
|
erjo@1850
|
621 } else {
|
erjo@1850
|
622 return 0;
|
erjo@1850
|
623 }
|
erjo@1850
|
624 }
|
erjo@1850
|
625
|
erjo@1850
|
626 sub parse_key_value {
|
erjo@1850
|
627 my $line = shift;
|
erjo@1850
|
628
|
erjo@1850
|
629 $line = del_comment($line);
|
erjo@1850
|
630 if ($line =~ /([^=]+)=(.+)/) {
|
erjo@1850
|
631 return (trim($1), trim($2));
|
erjo@1850
|
632 } else {
|
erjo@1850
|
633 return 0;
|
erjo@1850
|
634 }
|
erjo@1850
|
635 }
|
erjo@1850
|
636
|
erjo@1850
|
637 sub choose_target_os {
|
erjo@1850
|
638 my @targets = @_;
|
erjo@1850
|
639 my $arch = `uname -m`;
|
erjo@1850
|
640 chomp($arch);
|
erjo@1850
|
641 printf DBG "arch: %s\n", $arch;
|
erjo@1850
|
642 if ($arch =~ /64$/) {
|
erjo@1850
|
643 $arch = "amd64";
|
erjo@1850
|
644 } else {
|
erjo@1850
|
645 $arch = "x86";
|
erjo@1850
|
646 }
|
erjo@1850
|
647 printf DBG "arch: %s\n", $arch;
|
erjo@1850
|
648 my @prefs = ("NT($arch)\.5\.1", "NT($arch)\.5", "NT($arch)",
|
erjo@1850
|
649 "NT\.5\.1", "NT\.5", "NT");
|
erjo@1850
|
650 foreach my $pref (@prefs) {
|
erjo@1850
|
651 foreach my $target (@targets) {
|
erjo@1850
|
652 $target = trim($target);
|
erjo@1850
|
653 printf DBG "target: '%s', pref: '%s'\n", $target, $pref;
|
erjo@1850
|
654 if ($target =~ /NT((amd64)|(x86))/i) {
|
erjo@1850
|
655 printf DBG "target arch: '%s'\n", $1;
|
erjo@1850
|
656 next if ($1 !~ /$arch/i);
|
erjo@1850
|
657 }
|
erjo@1850
|
658 if ($target =~ /$pref/i) {
|
erjo@1850
|
659 return $target;
|
erjo@1850
|
660 }
|
erjo@1850
|
661 }
|
erjo@1850
|
662 }
|
erjo@1850
|
663 return "";
|
erjo@1850
|
664 }
|
erjo@1850
|
665
|
erjo@1850
|
666 sub get_target_os_section {
|
erjo@1850
|
667 my ($section, $target) = @_;
|
erjo@1850
|
668 my $lines;
|
erjo@1850
|
669
|
erjo@1850
|
670 chomp($section);
|
erjo@1850
|
671 $section =~ s/^\s*"\s*//;
|
erjo@1850
|
672 $section =~ s/\s*"\s*$//;
|
erjo@1850
|
673 printf DBG "section: \"%s\", target: \"%s\"\n", $section, $target;
|
erjo@1850
|
674
|
erjo@1850
|
675 if (length($target) gt 0) {
|
erjo@1850
|
676 $lines = get_section($section . "." . $target);
|
erjo@1850
|
677 return $lines if ($lines);
|
erjo@1850
|
678 }
|
erjo@1850
|
679
|
erjo@1850
|
680 my $arch = `uname -m`;
|
erjo@1850
|
681 chomp($arch);
|
erjo@1850
|
682 printf DBG "arch: %s\n", $arch;
|
erjo@1850
|
683 if ($arch =~ /64$/) {
|
erjo@1850
|
684 $arch = "AMD64";
|
erjo@1850
|
685 } else {
|
erjo@1850
|
686 $arch = "X86";
|
erjo@1850
|
687 }
|
erjo@1850
|
688 printf DBG "arch: %s\n", $arch;
|
erjo@1850
|
689
|
erjo@1850
|
690 my @prefs = ("NT$arch.5.1", "NT$arch.5", "NT$arch",
|
erjo@1850
|
691 "NT.5.1", "NT.5", "NT");
|
erjo@1850
|
692 foreach my $pref (@prefs) {
|
erjo@1850
|
693 $lines = get_section($section . "." . $pref);
|
erjo@1850
|
694 return $lines if ($lines);
|
erjo@1850
|
695 }
|
erjo@1850
|
696 $lines = get_section($section);
|
erjo@1850
|
697 return $lines if ($lines);
|
erjo@1850
|
698
|
erjo@1850
|
699 printf DBG "couldn't find section \"$section\" for \"$arch\"\n";
|
erjo@1850
|
700 return 0;
|
erjo@1850
|
701 }
|
erjo@1850
|
702
|
erjo@1850
|
703 sub get_section_value {
|
erjo@1850
|
704 (my $section, my $name) = @_;
|
erjo@1850
|
705 return $parsed_sections{$section}->{$name};
|
erjo@1850
|
706 }
|
erjo@1850
|
707
|
erjo@1850
|
708 sub get_string_value {
|
erjo@1850
|
709 my $key = shift;
|
erjo@1850
|
710 if ($key =~ /%(.+)%/) {
|
erjo@1850
|
711 $key = $1;
|
erjo@1850
|
712 return get_section_value("Strings", $key);
|
erjo@1850
|
713 } else {
|
erjo@1850
|
714 return $key;
|
erjo@1850
|
715 }
|
erjo@1850
|
716 }
|
erjo@1850
|
717
|
erjo@1850
|
718 sub copy_file {
|
erjo@1850
|
719 my ($src, $dst) = @_;
|
erjo@1850
|
720
|
erjo@1850
|
721 # ignore files not needed
|
erjo@1850
|
722 return 0 if (lc($src) =~ /\.((exe)|(dll)|(cpl)|(hlp))$/);
|
erjo@1850
|
723 my $real_file = get_file($src);
|
erjo@1850
|
724 if (length($real_file) gt 0) {
|
erjo@1850
|
725 $dst = lc($dst);
|
erjo@1850
|
726 printf DBG "copying \"$src_dir/$real_file\" to " .
|
erjo@1850
|
727 "\"$confdir/$driver_name/$dst\"\n";
|
erjo@1850
|
728 copy("$src_dir/$real_file", "$confdir/$driver_name/$dst") or
|
erjo@1850
|
729 warn "couldn't copy \"$src_dir/$real_file\" to " .
|
erjo@1850
|
730 "\"$confdir/$driver_name\": $! -\n" .
|
erjo@1850
|
731 "installation may be incomplete\n";
|
erjo@1850
|
732 printf DBG "chmod: $confdir/$driver_name/$dst\n";
|
erjo@1850
|
733 chmod(0644, "$confdir/$driver_name/$dst");
|
erjo@1850
|
734 if ($dst =~ /\.sys$/) {
|
erjo@1850
|
735 printf CONF "%s ", $dst;
|
erjo@1850
|
736 }
|
erjo@1850
|
737 } else {
|
erjo@1850
|
738 warn "couldn't find \"$src\" in \"$src_dir\"; make sure " .
|
erjo@1850
|
739 "all driver files, including .inf, .sys (and any firmware files) " .
|
erjo@1850
|
740 "are in \"$src_dir\" -\n" .
|
erjo@1850
|
741 "installation may be incomplete\n";
|
erjo@1850
|
742 }
|
erjo@1850
|
743 }
|
erjo@1850
|
744
|
erjo@1850
|
745
|
erjo@1850
|
746 # for conf files with subvendor and subdevice, create conf files with just
|
erjo@1850
|
747 # vendor and device
|
erjo@1850
|
748 sub create_fuzzy_conf {
|
erjo@1850
|
749 my $driver = shift;
|
erjo@1850
|
750 my $cwd = cwd();
|
erjo@1850
|
751 chdir("$confdir/$driver") or die "couldn't chdir to $confdir/$driver: $!";
|
erjo@1850
|
752 open(LS, "ls -1 . |") or die "couldn't open $confdir/$driver: $!";
|
erjo@1850
|
753 while (my $file = <LS>) {
|
erjo@1850
|
754 chomp($file);
|
erjo@1850
|
755 if ($file =~ /$re_sub_dev_conf/) {
|
erjo@1850
|
756 my $fuzzy_file = "$1:$2.$5.conf";
|
erjo@1850
|
757 printf DBG "file: $file, fuzzy file: $fuzzy_file\n";
|
erjo@1850
|
758 if (! -e "$confdir/$driver/$fuzzy_file") {
|
erjo@1850
|
759 symlink("$file", "$fuzzy_file") or
|
erjo@1850
|
760 warn "couldn't link $confdir/$driver/$file " .
|
erjo@1850
|
761 "to $confdir/$driver/$fuzzy_file: $!\n";
|
erjo@1850
|
762 }
|
erjo@1850
|
763 }
|
erjo@1850
|
764 }
|
erjo@1850
|
765 close(LS);
|
erjo@1850
|
766 chdir($cwd) or warn "couldn't chdir to $cwd: $!";
|
erjo@1850
|
767 return 0;
|
erjo@1850
|
768 }
|
erjo@1850
|
769
|
erjo@1850
|
770 # find a file in a case-insensitive way.
|
erjo@1850
|
771 sub get_file {
|
erjo@1850
|
772 my $file = lc(shift);
|
erjo@1850
|
773 if (opendir(DIR, "$src_dir")) {
|
erjo@1850
|
774 my @allfiles = readdir(DIR);
|
erjo@1850
|
775 foreach my $real_file (@allfiles) {
|
erjo@1850
|
776 if (lc($real_file) eq $file) {
|
erjo@1850
|
777 closedir(DIR);
|
erjo@1850
|
778 return $real_file;
|
erjo@1850
|
779 }
|
erjo@1850
|
780 }
|
erjo@1850
|
781 closedir(DIR);
|
erjo@1850
|
782 } else {
|
erjo@1850
|
783 warn "couldn't open \"$src_dir\": $! -\n" .
|
erjo@1850
|
784 "installation may be incomplete\n";
|
erjo@1850
|
785 }
|
erjo@1850
|
786 return "";
|
erjo@1850
|
787 }
|
erjo@1850
|
788
|
erjo@1850
|
789 sub strip_quotes {
|
erjo@1850
|
790 my $s = shift;
|
erjo@1850
|
791 $s =~ s/"(.*)"/$1/;
|
erjo@1850
|
792 return $s;
|
erjo@1850
|
793 }
|
erjo@1850
|
794
|
erjo@1850
|
795 sub del_comment {
|
erjo@1850
|
796 my $s = shift;
|
erjo@1850
|
797 $s =~ s/;.*//;
|
erjo@1850
|
798 return $s;
|
erjo@1850
|
799 }
|
erjo@1850
|
800
|
erjo@1850
|
801 # remove whitsepace at front and end.
|
erjo@1850
|
802 sub trim {
|
erjo@1850
|
803 my $s = shift;
|
erjo@1850
|
804 $s =~ s/^\s*//;
|
erjo@1850
|
805 $s =~ s/\s*$//;
|
erjo@1850
|
806 return $s;
|
erjo@1850
|
807 }
|
erjo@1850
|
808
|
erjo@1850
|
809 sub valid_copy_file_name {
|
erjo@1850
|
810 my $file = shift;
|
erjo@1850
|
811 $file = lc($file);
|
erjo@1850
|
812 printf DBG "file name: %s\n", $file;
|
erjo@1850
|
813 foreach my $disk_file (@source_disks_files) {
|
erjo@1850
|
814 return 1 if ($file eq $disk_file);
|
erjo@1850
|
815 }
|
erjo@1850
|
816 # some inf files may not have SourceDisksFiles section, so use
|
erjo@1850
|
817 # known file names
|
erjo@1850
|
818 return 1 if ($file =~ /\.((sys)|(bin)|(out))$/);
|
erjo@1850
|
819 return 0;
|
erjo@1850
|
820 }
|
erjo@1850
|
821
|
erjo@1850
|
822 sub parse_source_disks_files {
|
erjo@1850
|
823 my $lines = get_source_disks_files();
|
erjo@1850
|
824 if ($lines) {
|
erjo@1850
|
825 foreach my $line (@{$lines}) {
|
erjo@1850
|
826 $line = del_comment($line);
|
erjo@1850
|
827 next if (length($line) eq 0);
|
erjo@1850
|
828 my @file = split("=", $line);
|
erjo@1850
|
829 next if (@file eq 0 or length($file[0] eq 0));
|
erjo@1850
|
830 printf DBG "source disk file: \"%s\"\n", trim($file[0]);
|
erjo@1850
|
831 push (@source_disks_files, lc(trim($file[0])));
|
erjo@1850
|
832 }
|
erjo@1850
|
833 } else {
|
erjo@1850
|
834 warn "couldn't find SourceDisksFiles section - " .
|
erjo@1850
|
835 "continuing anyway...\n";
|
erjo@1850
|
836 }
|
erjo@1850
|
837 }
|
erjo@1850
|
838
|
erjo@1850
|
839 sub get_source_disks_files {
|
erjo@1850
|
840 my $arch = `uname -m`;
|
erjo@1850
|
841 chomp($arch);
|
erjo@1850
|
842 if ($arch =~ /64$/) {
|
erjo@1850
|
843 $arch = "AMD64";
|
erjo@1850
|
844 } else {
|
erjo@1850
|
845 $arch = "X86";
|
erjo@1850
|
846 }
|
erjo@1850
|
847
|
erjo@1850
|
848 my $lines = get_section("SourceDisksFiles." . $arch);
|
erjo@1850
|
849 return $lines if ($lines);
|
erjo@1850
|
850
|
erjo@1850
|
851 $lines = get_section("SourceDisksFiles");
|
erjo@1850
|
852 return $lines if ($lines);
|
erjo@1850
|
853
|
erjo@1850
|
854 return 0;
|
erjo@1850
|
855 }
|
erjo@1850
|
856
|
erjo@1850
|
857 sub device_driver_alias {
|
erjo@1850
|
858 my ($devid, $driver) = @_;
|
erjo@1850
|
859 my $done = 0;
|
erjo@1850
|
860
|
erjo@1850
|
861 $devid = uc($devid);
|
erjo@1850
|
862 if (!($devid =~ /^$re_dev_id:$re_dev_id$/)) {
|
erjo@1850
|
863 printf "'$devid' is not a valid device ID\n";
|
erjo@1850
|
864 return 1;
|
erjo@1850
|
865 }
|
erjo@1850
|
866 open(LS, "ls -1 $confdir/$driver/ |") or
|
erjo@1850
|
867 die "couldn't open $confdir/$driver: $!";
|
erjo@1850
|
868
|
erjo@1850
|
869 while (my $f = <LS>) {
|
erjo@1850
|
870 chomp($f);
|
erjo@1850
|
871 if ($f =~ /\.([[:xdigit:]]+)\.conf$/) {
|
erjo@1850
|
872 if (stat("$confdir/$driver/$devid.$1.conf")) {
|
erjo@1850
|
873 printf "Driver '$driver' is already used for '$devid'\n";
|
erjo@1850
|
874 $done = 1;
|
erjo@1850
|
875 last;
|
erjo@1850
|
876 }
|
erjo@1850
|
877 if (symlink("$f", "$confdir/$driver/$devid.$1.conf")) {
|
erjo@1850
|
878 printf "WARNING: Driver '$driver' will be used for '$devid'\n" .
|
erjo@1850
|
879 "This is safe _only_ if driver $driver is meant for " .
|
erjo@1850
|
880 "chip in device $devid\n";
|
erjo@1850
|
881 $done = 1;
|
erjo@1850
|
882 last;
|
erjo@1850
|
883 } else {
|
erjo@1850
|
884 warn "couldn't create symlink for \"$f\": $! -\n" .
|
erjo@1850
|
885 "installation may be incomplete\n";
|
erjo@1850
|
886 }
|
erjo@1850
|
887 }
|
erjo@1850
|
888 }
|
erjo@1850
|
889 close(LS);
|
erjo@1850
|
890 if ($done == 0) {
|
erjo@1850
|
891 printf "driver '$driver' is not installed (properly)!\n";
|
erjo@1850
|
892 return 1;
|
erjo@1850
|
893 }
|
erjo@1850
|
894 return 0;
|
erjo@1850
|
895 }
|
erjo@1850
|
896
|
erjo@1850
|
897 sub list_drivers {
|
erjo@1850
|
898 my $cards = get_cards();
|
erjo@1850
|
899 open(LS, "/bin/ls -1 $confdir|") or die "couldn't open $confdir: $!";
|
erjo@1850
|
900 while (my $driver = <LS>) {
|
erjo@1910
|
901 chomp($driver);
|
erjo@1910
|
902 if (-e "$confdir/$driver") {
|
erjo@1910
|
903 printf "%s : %s\n", $driver, install_status($cards, $driver);
|
erjo@1910
|
904 }
|
erjo@1850
|
905 }
|
erjo@1850
|
906 close(LS);
|
erjo@1850
|
907 return 0;
|
erjo@1850
|
908 }
|
erjo@1850
|
909
|
erjo@1850
|
910
|
erjo@1850
|
911 sub get_cards {
|
erjo@1850
|
912 #01:00.0 Class 0300: 1002:4c66 (rev 01)
|
erjo@1850
|
913 # Subsystem: 1043:1732
|
erjo@1850
|
914 my @cards = ();
|
erjo@1850
|
915 if (open(LSPCI, "/usr/bin/lspci -vn|")) {
|
erjo@1850
|
916 my $card;
|
erjo@1850
|
917 while (my $line = <LSPCI>) {
|
erjo@1850
|
918 if ($line =~ /^[0-9a-f]+.+\s$re_dev_id:$re_dev_id/) {
|
erjo@1850
|
919 $card = {vendor => uc($1), device => uc($2)};
|
erjo@1850
|
920 printf DBG "card: %s, %s\n", $1, $2;
|
erjo@1850
|
921 } elsif ($line =~ /.+Subsystem:\s$re_dev_id:$re_dev_id/) {
|
erjo@1850
|
922 $card->{subvendor} = uc($1);
|
erjo@1850
|
923 $card->{subdevice} = uc($2);
|
erjo@1850
|
924 printf DBG "sub: %s, %s\n", $1, $2;
|
erjo@1850
|
925 push(@cards, $card);
|
erjo@1850
|
926 }
|
erjo@1850
|
927 }
|
erjo@1850
|
928 close(LSPCI);
|
erjo@1850
|
929 }
|
erjo@1850
|
930
|
erjo@1850
|
931 if (open(LSUSB, "lsusb |")) {
|
erjo@1850
|
932 my $card;
|
erjo@1850
|
933 while (my $line = <LSUSB>) {
|
erjo@1850
|
934 if ($line =~ /.+: ID\s$re_dev_id:$re_dev_id/) {
|
erjo@1850
|
935 $card = {vendor => uc($1), device => uc($2)};
|
erjo@1850
|
936 push(@cards, $card);
|
erjo@1850
|
937 }
|
erjo@1850
|
938 }
|
erjo@1850
|
939 close(LSUSB);
|
erjo@1850
|
940 }
|
erjo@1850
|
941 return \@cards;
|
erjo@1850
|
942 }
|
erjo@1850
|
943
|
erjo@1850
|
944 sub install_status {
|
erjo@1850
|
945 my ($cards, $driver) = @_;
|
erjo@1850
|
946
|
erjo@1850
|
947 if (!$cards or !$driver) {
|
erjo@1850
|
948 return;
|
erjo@1850
|
949 }
|
erjo@1850
|
950
|
erjo@1850
|
951 my ($sys, $conf, $inf);
|
erjo@1850
|
952 my ($vendor, $device, $subvendor, $subdevice, $busid, $ret);
|
erjo@1850
|
953
|
erjo@1850
|
954 $sys = $conf = $inf = 0;
|
erjo@1850
|
955 open(LS2, "/bin/ls -1 $confdir/$driver|") or
|
erjo@1850
|
956 die "couldn't open $confdir/$driver: $!";
|
erjo@1850
|
957 while (my $file = <LS2>) {
|
erjo@1850
|
958 chomp($file);
|
erjo@1850
|
959 if ($file =~ /\.sys$/) {
|
erjo@1850
|
960 $sys = 1;
|
erjo@1850
|
961 } elsif ($file =~ /\.inf$/) {
|
erjo@1850
|
962 $inf = 1;
|
erjo@1850
|
963 } elsif ($file =~ /^$re_sub_dev_conf$/) {
|
erjo@1850
|
964 $busid = hex($5);
|
erjo@1850
|
965 $conf = 1 if ($busid eq $WRAP_PCI_BUS);
|
erjo@1850
|
966 } elsif ($file =~ /^$re_dev_conf$/) {
|
erjo@1850
|
967 $busid = hex($3);
|
erjo@1850
|
968 $conf = 1 if ($busid eq $WRAP_USB_BUS or $busid eq 0 or
|
erjo@1850
|
969 $busid eq $WRAP_PCI_BUS);
|
erjo@1850
|
970 }
|
erjo@1850
|
971 }
|
erjo@1850
|
972 close(LS2);
|
erjo@1850
|
973 printf DBG "status: $sys, $inf, $conf\n";
|
erjo@1850
|
974 if ($sys eq 0 or $inf eq 0 or $conf eq 0) {
|
erjo@1850
|
975 $ret = "invalid driver!";
|
erjo@1850
|
976 return $ret;
|
erjo@1850
|
977 }
|
erjo@1850
|
978 $ret = "driver installed";
|
erjo@1850
|
979 open(LS2, "/bin/ls -1 $confdir/$driver|") or
|
erjo@1850
|
980 die "couldn't open $confdir/$driver: $!";
|
erjo@1850
|
981
|
erjo@1850
|
982 while (my $file = <LS2>) {
|
erjo@1850
|
983 chomp($file);
|
erjo@1850
|
984 next if ($file !~ /\.conf$/);
|
erjo@1850
|
985 $conf = 0;
|
erjo@1850
|
986 if ($file =~ /^$re_sub_dev_conf$/) {
|
erjo@1850
|
987 ($vendor, $device, $subvendor, $subdevice, $busid) =
|
erjo@1850
|
988 (uc($1), uc($2), uc($3), uc($4), hex($5));
|
erjo@1850
|
989 $conf = 1;
|
erjo@1850
|
990 foreach my $card (@{$cards}) {
|
erjo@1850
|
991 if ($card->{vendor} eq $vendor and
|
erjo@1850
|
992 $card->{device} eq $device and
|
erjo@1850
|
993 $card->{subvendor} eq $subvendor and
|
erjo@1850
|
994 $card->{subdevice} eq $subdevice and
|
erjo@1850
|
995 $busid eq $WRAP_PCI_BUS) {
|
erjo@1850
|
996 $ret .= "\n\tdevice ($vendor:$device" .
|
erjo@1850
|
997 ":$subvendor:$subdevice) present";
|
erjo@1850
|
998 $conf = 2;
|
erjo@1850
|
999 last;
|
erjo@1850
|
1000 }
|
erjo@1850
|
1001 }
|
erjo@1850
|
1002 } elsif ($file =~ /^$re_dev_conf/) {
|
erjo@1850
|
1003 ($vendor, $device, $subvendor, $subdevice, $busid) =
|
erjo@1850
|
1004 (uc($1), uc($2), "\\*", "\\*", hex($3));
|
erjo@1850
|
1005 $conf = 1;
|
erjo@1850
|
1006 foreach my $card (@{$cards}) {
|
erjo@1850
|
1007 if ($card->{vendor} eq $vendor and
|
erjo@1850
|
1008 $card->{device} eq $device and
|
erjo@1850
|
1009 ($busid eq $WRAP_USB_BUS or $busid eq 0 or
|
erjo@1850
|
1010 $busid eq $WRAP_PCI_BUS)) {
|
erjo@1850
|
1011 $ret .= "\n\tdevice ($vendor:$device) present";
|
erjo@1850
|
1012 $conf = 2;
|
erjo@1850
|
1013 last;
|
erjo@1850
|
1014 }
|
erjo@1850
|
1015 }
|
erjo@1850
|
1016 }
|
erjo@1850
|
1017 next if ($conf le 1);
|
erjo@1850
|
1018 # find if kernel knows of an alternate driver for this device
|
erjo@1850
|
1019 my $devstring;
|
erjo@1850
|
1020 if ($busid eq $WRAP_USB_BUS or $busid eq 0) {
|
erjo@1850
|
1021 $devstring = sprintf("usb:v%sp%sd", $vendor, $device);
|
erjo@1850
|
1022 } elsif ($busid eq $WRAP_PCI_BUS) {
|
erjo@1850
|
1023 $devstring = sprintf("pci:v0000%sd0000%ssv", $vendor, $device);
|
erjo@1850
|
1024 } else {
|
erjo@1850
|
1025 next;
|
erjo@1850
|
1026 }
|
erjo@1850
|
1027 open(MODPROBE, "modprobe -c|") or next;
|
erjo@1850
|
1028 while (my $line = <MODPROBE>) {
|
erjo@1850
|
1029 my $alt;
|
erjo@1850
|
1030 chomp($line);
|
erjo@1850
|
1031 next if $line !~ /$devstring/;
|
erjo@1850
|
1032 $alt = (split(' ', $line))[-1];
|
erjo@1850
|
1033 chomp($alt);
|
erjo@1850
|
1034 if (length($alt) gt 0 and $alt ne "ndiswrapper") {
|
erjo@1850
|
1035 $ret .= " (alternate driver: $alt)";
|
erjo@1850
|
1036 last;
|
erjo@1850
|
1037 }
|
erjo@1850
|
1038 }
|
erjo@1850
|
1039 close(MODPROBE);
|
erjo@1850
|
1040 }
|
erjo@1850
|
1041 close(LS2);
|
erjo@1850
|
1042 printf DBG "driver: $driver, $ret\n";
|
erjo@1850
|
1043 return $ret;
|
erjo@1850
|
1044 }
|
erjo@1850
|
1045
|
erjo@1850
|
1046 ## Local Variables: ##
|
erjo@1850
|
1047 ## cperl-indent-level: 4 ##
|
erjo@1850
|
1048 ## End: ##
|