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