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@1950
|
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@1950
|
268 while(<LSMOD>) {
|
erjo@1950
|
269 if(/^ndiswrapper/){$tmp = 1;}
|
erjo@1950
|
270 }
|
erjo@1950
|
271 if(!$tmp) {
|
erjo@1941
|
272 print "Loading ndiswrapper...\n";
|
erjo@1941
|
273 `modprobe ndiswrapper`;
|
erjo@1941
|
274 }
|
erjo@1950
|
275 }
|
erjo@1950
|
276
|
erjo@1850
|
277 sub install {
|
erjo@1850
|
278 my $inf = shift;
|
erjo@1850
|
279 chomp($inf);
|
erjo@1893
|
280 chop($src_dir = `dirname $inf`);
|
erjo@1850
|
281 $driver_name = lc(basename($inf));
|
erjo@1850
|
282
|
erjo@1850
|
283 unless ($driver_name =~ s/\.inf$//) {
|
erjo@1850
|
284 die "install argument must be .inf file\n";
|
erjo@1850
|
285 }
|
erjo@1850
|
286
|
erjo@1850
|
287 if (! -d $confdir) {
|
erjo@1850
|
288 mkdir($confdir) or die "couldn't create $confdir: $!";
|
erjo@1850
|
289 }
|
erjo@1850
|
290 (-d "$confdir/$driver_name") and
|
erjo@1850
|
291 die "driver $driver_name is already installed\n";
|
erjo@1850
|
292
|
erjo@1850
|
293 read_sections($inf);
|
erjo@1850
|
294 parse_section("Strings");
|
erjo@1850
|
295 parse_section("Version");
|
erjo@1850
|
296 parse_source_disks_files();
|
erjo@1850
|
297 mkdir("$confdir/$driver_name") or
|
erjo@1850
|
298 die "couldn't create $confdir/$driver_name: $!";
|
erjo@1850
|
299 print "installing $driver_name ...\n";
|
erjo@1850
|
300 parse_mfr();
|
erjo@1850
|
301 copy_file(basename($inf), basename($inf));
|
erjo@1850
|
302 create_fuzzy_conf($driver_name);
|
erjo@1910
|
303
|
erjo@1910
|
304 #Update LOAD_MODULES and load ndiswrapper.
|
erjo@1942
|
305 # Only if we are not in debug mode.
|
erjo@1942
|
306 if (!$dbg) {
|
erjo@1942
|
307 set_rcs_config();
|
erjo@1942
|
308 load_ndiswrapper();
|
erjo@1942
|
309
|
erjo@1942
|
310 # Ask for WiFi at boot time.
|
erjo@1942
|
311 print "Would you to start WiFi at boot time [y/N]? ";
|
erjo@1942
|
312 chomp(my $answer = <STDIN>);
|
erjo@1942
|
313 if (lc($answer) eq "y") {
|
erjo@1942
|
314 set_net_config();
|
erjo@1942
|
315 }
|
erjo@1941
|
316 }
|
erjo@1893
|
317
|
erjo@1850
|
318 return 0;
|
erjo@1850
|
319 }
|
erjo@1850
|
320
|
erjo@1850
|
321 # return lines in section
|
erjo@1850
|
322 sub get_section {
|
erjo@1850
|
323 my $name = shift;
|
erjo@1850
|
324 foreach my $key (keys %sections) {
|
erjo@1850
|
325 if (lc($key) eq lc($name)) {
|
erjo@1850
|
326 printf DBG "section: $key\n";
|
erjo@1850
|
327 return \@{$sections{$key}};
|
erjo@1850
|
328 }
|
erjo@1850
|
329 }
|
erjo@1850
|
330 printf DBG "couldn't find section \"$name\"\n";
|
erjo@1850
|
331 return 0;
|
erjo@1850
|
332 }
|
erjo@1850
|
333
|
erjo@1850
|
334 # load inf and split into different sections.
|
erjo@1850
|
335 sub read_sections {
|
erjo@1850
|
336 my $filename = shift;
|
erjo@1850
|
337 open(INF, $filename) or die "couldn't open $filename: $!";
|
erjo@1850
|
338
|
erjo@1850
|
339 my $name = "none";
|
erjo@1850
|
340 @{$sections{$name}} = ();
|
erjo@1850
|
341 while (my $line = <INF>) {
|
erjo@1850
|
342 # convert from unicode
|
erjo@1850
|
343 $line =~ s/\xff\xfe//;
|
erjo@1850
|
344 $line =~ s/\0//g;
|
erjo@1850
|
345
|
erjo@1850
|
346 chomp($line);
|
erjo@1850
|
347 $line = trim($line);
|
erjo@1850
|
348 next if ($line =~ /^$/);
|
erjo@1850
|
349 if ($line =~ /^\[(.+)\]/) {
|
erjo@1850
|
350 $name = $1;
|
erjo@1850
|
351 @{$sections{$name}} = ();
|
erjo@1850
|
352 } else {
|
erjo@1850
|
353 push(@{$sections{$name}}, $line);
|
erjo@1850
|
354 }
|
erjo@1850
|
355 }
|
erjo@1850
|
356 close(INF);
|
erjo@1850
|
357 foreach $name (keys %sections) {
|
erjo@1850
|
358 printf DBG "section: %s\n", $name;
|
erjo@1850
|
359 foreach my $line (@{$sections{$name}}) {
|
erjo@1850
|
360 printf DBG "%s: %s\n", $name, $line;
|
erjo@1850
|
361 }
|
erjo@1850
|
362 }
|
erjo@1850
|
363 }
|
erjo@1850
|
364
|
erjo@1850
|
365 sub parse_section {
|
erjo@1850
|
366 my $name = shift;
|
erjo@1850
|
367 my $lines = get_section($name);
|
erjo@1850
|
368 if (!$lines) {
|
erjo@1950
|
369 return;
|
erjo@1850
|
370 }
|
erjo@1850
|
371 $parsed_sections{$name} = ();
|
erjo@1850
|
372 foreach my $line (@{$lines}) {
|
erjo@1850
|
373 (my $key, my $val) = parse_key_value($line);
|
erjo@1850
|
374 if ($key) {
|
erjo@1850
|
375 $val = strip_quotes($val);
|
erjo@1850
|
376 $parsed_sections{$name}->{$key} = $val;
|
erjo@1850
|
377 printf DBG "$name: %s = %s\n", $key, $val;
|
erjo@1850
|
378 }
|
erjo@1850
|
379 }
|
erjo@1850
|
380 }
|
erjo@1850
|
381
|
erjo@1850
|
382 sub parse_mfr() {
|
erjo@1850
|
383 my $lines = get_section("Manufacturer");
|
erjo@1850
|
384 $lines or die "couldn't get manufacturer section - " .
|
erjo@1850
|
385 "installation may be incomplete\n";
|
erjo@1850
|
386 foreach my $line (@{$lines}) {
|
erjo@1850
|
387 my ($strkey, $val) = parse_key_value($line);
|
erjo@1850
|
388 if ($strkey) {
|
erjo@1850
|
389 my ($models, @targets) = split(",", $val);
|
erjo@1850
|
390 if ($models) {
|
erjo@1850
|
391 printf DBG "mfr: %s, %s\n", $line, $models;
|
erjo@1850
|
392 my $target = choose_target_os(@targets);
|
erjo@1850
|
393 printf DBG "target: '%s'\n", $target;
|
erjo@1850
|
394 parse_models($models, $target);
|
erjo@1850
|
395 }
|
erjo@1850
|
396 }
|
erjo@1850
|
397 }
|
erjo@1850
|
398 }
|
erjo@1850
|
399
|
erjo@1850
|
400 sub parse_models {
|
erjo@1850
|
401 my ($models, $target) = @_;
|
erjo@1850
|
402 printf DBG "models: target: '%s'.'%s'\n", $models, $target;
|
erjo@1850
|
403 my $lines = get_target_os_section($models, $target);
|
erjo@1850
|
404 if (!$lines) {
|
erjo@1850
|
405 warn "couldn't find models section \"$models\" -\n" .
|
erjo@1850
|
406 "installation may be incomplete\n";
|
erjo@1850
|
407 return -1;
|
erjo@1850
|
408 }
|
erjo@1850
|
409 foreach my $line (@{$lines}) {
|
erjo@1850
|
410 $line = del_comment($line);
|
erjo@1850
|
411 next if (length($line) eq 0);
|
erjo@1850
|
412 (my $dev_desc, my $val) = parse_key_value($line);
|
erjo@1850
|
413 my @fields = split(",", $val);
|
erjo@1850
|
414 if (@fields le 1) {
|
erjo@1850
|
415 printf "couldn't find install directive: %s\n", $line;
|
erjo@1850
|
416 next;
|
erjo@1850
|
417 }
|
erjo@1850
|
418 my $section = trim($fields[0]);
|
erjo@1850
|
419 my $hwid = trim($fields[1]);
|
erjo@1850
|
420 if ($hwid =~ /^%.+%$/) {
|
erjo@1850
|
421 $hwid = get_string_value($hwid);
|
erjo@1850
|
422 }
|
erjo@1850
|
423 # TODO: deal with compatible IDs as hwid?
|
erjo@1850
|
424 my ($bus_type, $vendor, $device, $subvendor, $subdevice) =
|
erjo@1850
|
425 parse_hwid($hwid);
|
erjo@1850
|
426 next if (!$vendor);
|
erjo@1850
|
427 printf DBG "models: %s, %s, %s\n", $section, $hwid, $vendor;
|
erjo@1850
|
428 parse_install($section, $target, $bus_type, $vendor, $device,
|
erjo@1850
|
429 $subvendor, $subdevice);
|
erjo@1850
|
430 }
|
erjo@1850
|
431 }
|
erjo@1850
|
432
|
erjo@1850
|
433 sub parse_install {
|
erjo@1850
|
434 my ($section, $target, $bus_type, $vendor, $device,
|
erjo@1850
|
435 $subvendor, $subdevice) = @_;
|
erjo@1850
|
436 my $lines = get_target_os_section($section, $target);
|
erjo@1850
|
437 if (!$lines) {
|
erjo@1850
|
438 warn "couldn't find install section \"$section\" -\n" .
|
erjo@1850
|
439 "installation may be incomplete\n";
|
erjo@1850
|
440 return -1;
|
erjo@1850
|
441 }
|
erjo@1850
|
442
|
erjo@1850
|
443 my $filename = "$vendor:$device";
|
erjo@1850
|
444 if ($subvendor) {
|
erjo@1850
|
445 $filename .= ":$subvendor:$subdevice"
|
erjo@1850
|
446 }
|
erjo@1850
|
447 $filename .= sprintf(".%X.conf", $bus_type);
|
erjo@1850
|
448
|
erjo@1850
|
449 my (@addregs, @copyfiles);
|
erjo@1850
|
450 foreach my $line (@{$lines}) {
|
erjo@1850
|
451 $line =~ s/^;\s*//;
|
erjo@1850
|
452 $line = trim(del_comment($line));
|
erjo@1850
|
453 my ($key, $val) = parse_key_value($line);
|
erjo@1850
|
454 my @array;
|
erjo@1850
|
455 if ($key) {
|
erjo@1850
|
456 if (lc($key) eq "addreg") {
|
erjo@1850
|
457 @array = split(",", $val);
|
erjo@1850
|
458 foreach my $reg (@array) {
|
erjo@1850
|
459 push @addregs, trim($reg);
|
erjo@1850
|
460 }
|
erjo@1850
|
461 } elsif (lc($key) eq "copyfiles") {
|
erjo@1850
|
462 printf DBG "copyfiles: %s\n", $val;
|
erjo@1850
|
463 @array = split(",", $val);
|
erjo@1850
|
464 foreach my $copy_file_dirs (@array) {
|
erjo@1850
|
465 my @copy_sec = split(",", $copy_file_dirs);
|
erjo@1850
|
466 foreach my $file (@copy_sec) {
|
erjo@1850
|
467 push @copyfiles, trim($file);
|
erjo@1850
|
468 }
|
erjo@1850
|
469 }
|
erjo@1850
|
470 } elsif (lc($key) eq "bustype") {
|
erjo@1850
|
471 printf DBG "bustype: %s\n", $val;
|
erjo@1850
|
472 $bus_type = $val;
|
erjo@1850
|
473 }
|
erjo@1850
|
474 }
|
erjo@1850
|
475 }
|
erjo@1850
|
476
|
erjo@1850
|
477 open(CONF, ">$confdir/$driver_name/$filename") or
|
erjo@1850
|
478 die "couldn't create file $confdir/$driver_name/$filename: $!";
|
erjo@1850
|
479
|
erjo@1850
|
480 printf CONF "sys_files|";
|
erjo@1850
|
481 foreach my $file (@copyfiles) {
|
erjo@1950
|
482 parse_copy_file($file);
|
erjo@1850
|
483 }
|
erjo@1850
|
484 printf CONF "\n";
|
erjo@1850
|
485
|
erjo@1850
|
486 my $version = get_section_value("Version", "DriverVer");
|
erjo@1850
|
487 my $provider = get_section_value("Version", "Provider");
|
erjo@1850
|
488 my $classguid = get_section_value("Version", "ClassGUID");
|
erjo@1850
|
489 my $providerstring = trim(strip_quotes(get_string_value(trim($provider))));
|
erjo@1850
|
490 $classguid =~ s/^\s*{//;
|
erjo@1850
|
491 $classguid =~ s/}\s*$//;
|
erjo@1850
|
492
|
erjo@1850
|
493 printf CONF "NdisVersion|0x50001\n";
|
erjo@1850
|
494 printf CONF "Environment|1\n";
|
erjo@1850
|
495 printf CONF "class_guid|%s\n", $classguid;
|
erjo@1850
|
496 printf CONF "driver_version|%s,%s\n", $providerstring, $version;
|
erjo@1850
|
497 printf CONF "BusType|%s\n", $bus_type;
|
erjo@1850
|
498 printf CONF "SlotNumber|01\n";
|
erjo@1850
|
499 printf CONF "NetCfgInstanceId|{28022A01-1234-5678-ABCDE-123813291A00}\n";
|
erjo@1850
|
500 printf CONF "\n";
|
erjo@1850
|
501 close(CONF);
|
erjo@1850
|
502
|
erjo@1850
|
503 open(CONF, "|sort|uniq >>$confdir/$driver_name/$filename") or
|
erjo@1850
|
504 die "couldn't create file $confdir/$driver_name/$filename: $!";
|
erjo@1850
|
505
|
erjo@1850
|
506 foreach my $reg (@addregs) {
|
erjo@1950
|
507 parse_registry($reg);
|
erjo@1850
|
508 }
|
erjo@1850
|
509 close(CONF);
|
erjo@1850
|
510 }
|
erjo@1850
|
511
|
erjo@1850
|
512 sub parse_registry {
|
erjo@1850
|
513 my ($reg, $conf) = @_;
|
erjo@1850
|
514 my $lines = get_section($reg);
|
erjo@1850
|
515 if (!$lines) {
|
erjo@1850
|
516 warn "couldn't find section \"$reg\" -\n" .
|
erjo@1850
|
517 "installation may be incomplete\n";
|
erjo@1850
|
518 return -1;
|
erjo@1850
|
519 }
|
erjo@1850
|
520
|
erjo@1850
|
521 my $driver_desc = 0;
|
erjo@1850
|
522 foreach my $line (@{$lines}) {
|
erjo@1850
|
523 $line = del_comment($line);
|
erjo@1850
|
524 my @fields = split(",", $line);
|
erjo@1850
|
525 next if (@fields lt 4);
|
erjo@1850
|
526 my $value;
|
erjo@1850
|
527 my $param = trim($fields[1]);
|
erjo@1850
|
528 if ($param =~ /^ndi\\/i) {
|
erjo@1850
|
529 if ($param =~ /^ndi\\params\\(.+)/i) {
|
erjo@1850
|
530 $param = strip_quotes(trim($1));
|
erjo@1850
|
531 $param =~ s/\\.*$//;
|
erjo@1850
|
532 next if (lc(trim($fields[2])) ne "default");
|
erjo@1850
|
533 $value = strip_quotes(trim($fields[4]));
|
erjo@1850
|
534 } else {
|
erjo@1850
|
535 printf DBG "ignoring parameter $line\n";
|
erjo@1850
|
536 next;
|
erjo@1850
|
537 }
|
erjo@1850
|
538 } else {
|
erjo@1850
|
539 $param = strip_quotes(trim($fields[2]));
|
erjo@1850
|
540 next if (length($param) eq 0);
|
erjo@1850
|
541 $value = strip_quotes(trim($fields[4]));
|
erjo@1850
|
542 }
|
erjo@1850
|
543 $value = get_string_value($value);
|
erjo@1850
|
544 if (length($param) gt 0) {
|
erjo@1850
|
545 if ($param_fixlist{"$param|$value"}) {
|
erjo@1850
|
546 my $orig_value = $value;
|
erjo@1850
|
547 $value = $param_fixlist{"$param|$value"};
|
erjo@1850
|
548 printf "forcing parameter $param from $orig_value to $value\n";
|
erjo@1850
|
549 }
|
erjo@1850
|
550 printf CONF "%s|%s\n", $param, $value;
|
erjo@1850
|
551 if ($param =~ /^DriverDesc$/) {
|
erjo@1850
|
552 $driver_desc = 1;
|
erjo@1850
|
553 }
|
erjo@1850
|
554 }
|
erjo@1850
|
555 }
|
erjo@1850
|
556 if ($driver_desc == 0) {
|
erjo@1850
|
557 printf CONF "DriverDesc|NDIS Network Adapter\n";
|
erjo@1850
|
558 }
|
erjo@1850
|
559 }
|
erjo@1850
|
560
|
erjo@1850
|
561 sub parse_copy_file {
|
erjo@1850
|
562 my $copy_name = shift;
|
erjo@1850
|
563
|
erjo@1850
|
564 if ($copy_name =~ /^\@/) {
|
erjo@1850
|
565 $copy_name =~ s/^\@//;
|
erjo@1850
|
566 $copy_name = trim($copy_name);
|
erjo@1850
|
567 if (valid_copy_file_name($copy_name)) {
|
erjo@1850
|
568 return copy_file($copy_name, $copy_name);
|
erjo@1850
|
569 }
|
erjo@1850
|
570 }
|
erjo@1850
|
571
|
erjo@1850
|
572 my $lines = get_section($copy_name);
|
erjo@1850
|
573 if (!$lines) {
|
erjo@1850
|
574 warn "couldn't find section \"$copy_name\" -\n" .
|
erjo@1850
|
575 "installation may be incomplete\n";
|
erjo@1850
|
576 return -1;
|
erjo@1850
|
577 }
|
erjo@1850
|
578 foreach my $line (@{$lines}) {
|
erjo@1850
|
579 $line = trim($line);
|
erjo@1850
|
580
|
erjo@1850
|
581 # some inf files have file names commented out; get file names from them
|
erjo@1850
|
582 $line =~ s/^\s*;//;
|
erjo@1850
|
583 my @files = split(",", $line);
|
erjo@1850
|
584 if (@files == 0) {
|
erjo@1850
|
585 printf DBG "copyfiles section $copy_name has no files\n";
|
erjo@1850
|
586 return -1;
|
erjo@1850
|
587 }
|
erjo@1850
|
588 my $src, my $dst;
|
erjo@1850
|
589 if (@files > 1 and length(trim($files[1])) > 0) {
|
erjo@1850
|
590 $src = $files[1];
|
erjo@1850
|
591 if (length(trim($files[0])) > 0) {
|
erjo@1850
|
592 $dst = $files[0];
|
erjo@1850
|
593 } else {
|
erjo@1850
|
594 $dst = $src;
|
erjo@1850
|
595 }
|
erjo@1850
|
596 } else {
|
erjo@1850
|
597 $src = $files[0];
|
erjo@1850
|
598 $dst = $src;
|
erjo@1850
|
599 }
|
erjo@1850
|
600 $src =~ s/^.*\\//;
|
erjo@1850
|
601 $dst =~ s/^.*\\//;
|
erjo@1850
|
602 printf DBG "src: '%s', dst: '%s'\n", $src, $dst;
|
erjo@1850
|
603 $src = trim(del_comment($src));
|
erjo@1850
|
604 next if (length($src) eq 0);
|
erjo@1850
|
605 if (valid_copy_file_name($src)) {
|
erjo@1850
|
606 $dst = trim(del_comment($dst));
|
erjo@1850
|
607 printf DBG "src: '%s', dst: '%s'\n", $src, $dst;
|
erjo@1850
|
608 copy_file($src, $dst);
|
erjo@1850
|
609 } else {
|
erjo@1850
|
610 printf DBG "invalid file '%s' ignored\n", $src;
|
erjo@1850
|
611 }
|
erjo@1850
|
612 }
|
erjo@1850
|
613 return 0;
|
erjo@1850
|
614 }
|
erjo@1850
|
615
|
erjo@1850
|
616 sub parse_hwid {
|
erjo@1850
|
617 my $hwid = uc(shift);
|
erjo@1850
|
618 if ($hwid =~ /(PCI\\)?VEN_(\w+)&DEV_(\w+)&SUBSYS_(\w{4})(\S{4})/) {
|
erjo@1850
|
619 return ($WRAP_PCI_BUS, $2, $3, $4, $5);
|
erjo@1850
|
620 } elsif ($hwid =~ /(PCI\\)?VEN_(\w+)&DEV_(\w+)/) {
|
erjo@1850
|
621 return ($WRAP_PCI_BUS, $2, $3, 0, 0);
|
erjo@1850
|
622 } elsif ($hwid =~ /(USB\\)?VID_(\w+)&PID_(\w+)/) {
|
erjo@1850
|
623 return ($WRAP_USB_BUS, $2, $3, 0, 0);
|
erjo@1850
|
624 } else {
|
erjo@1850
|
625 return 0;
|
erjo@1850
|
626 }
|
erjo@1850
|
627 }
|
erjo@1850
|
628
|
erjo@1850
|
629 sub parse_key_value {
|
erjo@1850
|
630 my $line = shift;
|
erjo@1850
|
631
|
erjo@1850
|
632 $line = del_comment($line);
|
erjo@1850
|
633 if ($line =~ /([^=]+)=(.+)/) {
|
erjo@1850
|
634 return (trim($1), trim($2));
|
erjo@1850
|
635 } else {
|
erjo@1850
|
636 return 0;
|
erjo@1850
|
637 }
|
erjo@1850
|
638 }
|
erjo@1850
|
639
|
erjo@1850
|
640 sub choose_target_os {
|
erjo@1850
|
641 my @targets = @_;
|
erjo@1850
|
642 my $arch = `uname -m`;
|
erjo@1850
|
643 chomp($arch);
|
erjo@1850
|
644 printf DBG "arch: %s\n", $arch;
|
erjo@1850
|
645 if ($arch =~ /64$/) {
|
erjo@1850
|
646 $arch = "amd64";
|
erjo@1850
|
647 } else {
|
erjo@1850
|
648 $arch = "x86";
|
erjo@1850
|
649 }
|
erjo@1850
|
650 printf DBG "arch: %s\n", $arch;
|
erjo@1850
|
651 my @prefs = ("NT($arch)\.5\.1", "NT($arch)\.5", "NT($arch)",
|
erjo@1850
|
652 "NT\.5\.1", "NT\.5", "NT");
|
erjo@1850
|
653 foreach my $pref (@prefs) {
|
erjo@1850
|
654 foreach my $target (@targets) {
|
erjo@1850
|
655 $target = trim($target);
|
erjo@1850
|
656 printf DBG "target: '%s', pref: '%s'\n", $target, $pref;
|
erjo@1850
|
657 if ($target =~ /NT((amd64)|(x86))/i) {
|
erjo@1850
|
658 printf DBG "target arch: '%s'\n", $1;
|
erjo@1850
|
659 next if ($1 !~ /$arch/i);
|
erjo@1850
|
660 }
|
erjo@1850
|
661 if ($target =~ /$pref/i) {
|
erjo@1850
|
662 return $target;
|
erjo@1850
|
663 }
|
erjo@1850
|
664 }
|
erjo@1850
|
665 }
|
erjo@1850
|
666 return "";
|
erjo@1850
|
667 }
|
erjo@1850
|
668
|
erjo@1850
|
669 sub get_target_os_section {
|
erjo@1850
|
670 my ($section, $target) = @_;
|
erjo@1850
|
671 my $lines;
|
erjo@1850
|
672
|
erjo@1850
|
673 chomp($section);
|
erjo@1850
|
674 $section =~ s/^\s*"\s*//;
|
erjo@1850
|
675 $section =~ s/\s*"\s*$//;
|
erjo@1850
|
676 printf DBG "section: \"%s\", target: \"%s\"\n", $section, $target;
|
erjo@1850
|
677
|
erjo@1850
|
678 if (length($target) gt 0) {
|
erjo@1850
|
679 $lines = get_section($section . "." . $target);
|
erjo@1850
|
680 return $lines if ($lines);
|
erjo@1850
|
681 }
|
erjo@1850
|
682
|
erjo@1850
|
683 my $arch = `uname -m`;
|
erjo@1850
|
684 chomp($arch);
|
erjo@1850
|
685 printf DBG "arch: %s\n", $arch;
|
erjo@1850
|
686 if ($arch =~ /64$/) {
|
erjo@1850
|
687 $arch = "AMD64";
|
erjo@1850
|
688 } else {
|
erjo@1850
|
689 $arch = "X86";
|
erjo@1850
|
690 }
|
erjo@1850
|
691 printf DBG "arch: %s\n", $arch;
|
erjo@1850
|
692
|
erjo@1850
|
693 my @prefs = ("NT$arch.5.1", "NT$arch.5", "NT$arch",
|
erjo@1850
|
694 "NT.5.1", "NT.5", "NT");
|
erjo@1850
|
695 foreach my $pref (@prefs) {
|
erjo@1850
|
696 $lines = get_section($section . "." . $pref);
|
erjo@1850
|
697 return $lines if ($lines);
|
erjo@1850
|
698 }
|
erjo@1850
|
699 $lines = get_section($section);
|
erjo@1850
|
700 return $lines if ($lines);
|
erjo@1850
|
701
|
erjo@1850
|
702 printf DBG "couldn't find section \"$section\" for \"$arch\"\n";
|
erjo@1850
|
703 return 0;
|
erjo@1850
|
704 }
|
erjo@1850
|
705
|
erjo@1850
|
706 sub get_section_value {
|
erjo@1850
|
707 (my $section, my $name) = @_;
|
erjo@1850
|
708 return $parsed_sections{$section}->{$name};
|
erjo@1850
|
709 }
|
erjo@1850
|
710
|
erjo@1850
|
711 sub get_string_value {
|
erjo@1850
|
712 my $key = shift;
|
erjo@1850
|
713 if ($key =~ /%(.+)%/) {
|
erjo@1850
|
714 $key = $1;
|
erjo@1850
|
715 return get_section_value("Strings", $key);
|
erjo@1850
|
716 } else {
|
erjo@1850
|
717 return $key;
|
erjo@1850
|
718 }
|
erjo@1850
|
719 }
|
erjo@1850
|
720
|
erjo@1850
|
721 sub copy_file {
|
erjo@1850
|
722 my ($src, $dst) = @_;
|
erjo@1850
|
723
|
erjo@1850
|
724 # ignore files not needed
|
erjo@1850
|
725 return 0 if (lc($src) =~ /\.((exe)|(dll)|(cpl)|(hlp))$/);
|
erjo@1850
|
726 my $real_file = get_file($src);
|
erjo@1850
|
727 if (length($real_file) gt 0) {
|
erjo@1850
|
728 $dst = lc($dst);
|
erjo@1850
|
729 printf DBG "copying \"$src_dir/$real_file\" to " .
|
erjo@1850
|
730 "\"$confdir/$driver_name/$dst\"\n";
|
erjo@1850
|
731 copy("$src_dir/$real_file", "$confdir/$driver_name/$dst") or
|
erjo@1850
|
732 warn "couldn't copy \"$src_dir/$real_file\" to " .
|
erjo@1850
|
733 "\"$confdir/$driver_name\": $! -\n" .
|
erjo@1850
|
734 "installation may be incomplete\n";
|
erjo@1850
|
735 printf DBG "chmod: $confdir/$driver_name/$dst\n";
|
erjo@1850
|
736 chmod(0644, "$confdir/$driver_name/$dst");
|
erjo@1850
|
737 if ($dst =~ /\.sys$/) {
|
erjo@1850
|
738 printf CONF "%s ", $dst;
|
erjo@1850
|
739 }
|
erjo@1850
|
740 } else {
|
erjo@1850
|
741 warn "couldn't find \"$src\" in \"$src_dir\"; make sure " .
|
erjo@1850
|
742 "all driver files, including .inf, .sys (and any firmware files) " .
|
erjo@1850
|
743 "are in \"$src_dir\" -\n" .
|
erjo@1850
|
744 "installation may be incomplete\n";
|
erjo@1850
|
745 }
|
erjo@1850
|
746 }
|
erjo@1850
|
747
|
erjo@1850
|
748
|
erjo@1850
|
749 # for conf files with subvendor and subdevice, create conf files with just
|
erjo@1850
|
750 # vendor and device
|
erjo@1850
|
751 sub create_fuzzy_conf {
|
erjo@1850
|
752 my $driver = shift;
|
erjo@1850
|
753 my $cwd = cwd();
|
erjo@1850
|
754 chdir("$confdir/$driver") or die "couldn't chdir to $confdir/$driver: $!";
|
erjo@1850
|
755 open(LS, "ls -1 . |") or die "couldn't open $confdir/$driver: $!";
|
erjo@1850
|
756 while (my $file = <LS>) {
|
erjo@1850
|
757 chomp($file);
|
erjo@1850
|
758 if ($file =~ /$re_sub_dev_conf/) {
|
erjo@1850
|
759 my $fuzzy_file = "$1:$2.$5.conf";
|
erjo@1850
|
760 printf DBG "file: $file, fuzzy file: $fuzzy_file\n";
|
erjo@1850
|
761 if (! -e "$confdir/$driver/$fuzzy_file") {
|
erjo@1850
|
762 symlink("$file", "$fuzzy_file") or
|
erjo@1850
|
763 warn "couldn't link $confdir/$driver/$file " .
|
erjo@1850
|
764 "to $confdir/$driver/$fuzzy_file: $!\n";
|
erjo@1850
|
765 }
|
erjo@1850
|
766 }
|
erjo@1850
|
767 }
|
erjo@1850
|
768 close(LS);
|
erjo@1850
|
769 chdir($cwd) or warn "couldn't chdir to $cwd: $!";
|
erjo@1850
|
770 return 0;
|
erjo@1850
|
771 }
|
erjo@1850
|
772
|
erjo@1850
|
773 # find a file in a case-insensitive way.
|
erjo@1850
|
774 sub get_file {
|
erjo@1850
|
775 my $file = lc(shift);
|
erjo@1850
|
776 if (opendir(DIR, "$src_dir")) {
|
erjo@1850
|
777 my @allfiles = readdir(DIR);
|
erjo@1850
|
778 foreach my $real_file (@allfiles) {
|
erjo@1850
|
779 if (lc($real_file) eq $file) {
|
erjo@1850
|
780 closedir(DIR);
|
erjo@1850
|
781 return $real_file;
|
erjo@1850
|
782 }
|
erjo@1850
|
783 }
|
erjo@1850
|
784 closedir(DIR);
|
erjo@1850
|
785 } else {
|
erjo@1850
|
786 warn "couldn't open \"$src_dir\": $! -\n" .
|
erjo@1850
|
787 "installation may be incomplete\n";
|
erjo@1850
|
788 }
|
erjo@1850
|
789 return "";
|
erjo@1850
|
790 }
|
erjo@1850
|
791
|
erjo@1850
|
792 sub strip_quotes {
|
erjo@1850
|
793 my $s = shift;
|
erjo@1850
|
794 $s =~ s/"(.*)"/$1/;
|
erjo@1850
|
795 return $s;
|
erjo@1850
|
796 }
|
erjo@1850
|
797
|
erjo@1850
|
798 sub del_comment {
|
erjo@1850
|
799 my $s = shift;
|
erjo@1850
|
800 $s =~ s/;.*//;
|
erjo@1850
|
801 return $s;
|
erjo@1850
|
802 }
|
erjo@1850
|
803
|
erjo@1850
|
804 # remove whitsepace at front and end.
|
erjo@1850
|
805 sub trim {
|
erjo@1850
|
806 my $s = shift;
|
erjo@1850
|
807 $s =~ s/^\s*//;
|
erjo@1850
|
808 $s =~ s/\s*$//;
|
erjo@1850
|
809 return $s;
|
erjo@1850
|
810 }
|
erjo@1850
|
811
|
erjo@1850
|
812 sub valid_copy_file_name {
|
erjo@1850
|
813 my $file = shift;
|
erjo@1850
|
814 $file = lc($file);
|
erjo@1850
|
815 printf DBG "file name: %s\n", $file;
|
erjo@1850
|
816 foreach my $disk_file (@source_disks_files) {
|
erjo@1850
|
817 return 1 if ($file eq $disk_file);
|
erjo@1850
|
818 }
|
erjo@1850
|
819 # some inf files may not have SourceDisksFiles section, so use
|
erjo@1850
|
820 # known file names
|
erjo@1850
|
821 return 1 if ($file =~ /\.((sys)|(bin)|(out))$/);
|
erjo@1850
|
822 return 0;
|
erjo@1850
|
823 }
|
erjo@1850
|
824
|
erjo@1850
|
825 sub parse_source_disks_files {
|
erjo@1850
|
826 my $lines = get_source_disks_files();
|
erjo@1850
|
827 if ($lines) {
|
erjo@1850
|
828 foreach my $line (@{$lines}) {
|
erjo@1850
|
829 $line = del_comment($line);
|
erjo@1850
|
830 next if (length($line) eq 0);
|
erjo@1850
|
831 my @file = split("=", $line);
|
erjo@1850
|
832 next if (@file eq 0 or length($file[0] eq 0));
|
erjo@1850
|
833 printf DBG "source disk file: \"%s\"\n", trim($file[0]);
|
erjo@1850
|
834 push (@source_disks_files, lc(trim($file[0])));
|
erjo@1850
|
835 }
|
erjo@1850
|
836 } else {
|
erjo@1850
|
837 warn "couldn't find SourceDisksFiles section - " .
|
erjo@1850
|
838 "continuing anyway...\n";
|
erjo@1850
|
839 }
|
erjo@1850
|
840 }
|
erjo@1850
|
841
|
erjo@1850
|
842 sub get_source_disks_files {
|
erjo@1850
|
843 my $arch = `uname -m`;
|
erjo@1850
|
844 chomp($arch);
|
erjo@1850
|
845 if ($arch =~ /64$/) {
|
erjo@1850
|
846 $arch = "AMD64";
|
erjo@1850
|
847 } else {
|
erjo@1850
|
848 $arch = "X86";
|
erjo@1850
|
849 }
|
erjo@1850
|
850
|
erjo@1850
|
851 my $lines = get_section("SourceDisksFiles." . $arch);
|
erjo@1850
|
852 return $lines if ($lines);
|
erjo@1850
|
853
|
erjo@1850
|
854 $lines = get_section("SourceDisksFiles");
|
erjo@1850
|
855 return $lines if ($lines);
|
erjo@1850
|
856
|
erjo@1850
|
857 return 0;
|
erjo@1850
|
858 }
|
erjo@1850
|
859
|
erjo@1850
|
860 sub device_driver_alias {
|
erjo@1850
|
861 my ($devid, $driver) = @_;
|
erjo@1850
|
862 my $done = 0;
|
erjo@1850
|
863
|
erjo@1850
|
864 $devid = uc($devid);
|
erjo@1850
|
865 if (!($devid =~ /^$re_dev_id:$re_dev_id$/)) {
|
erjo@1850
|
866 printf "'$devid' is not a valid device ID\n";
|
erjo@1850
|
867 return 1;
|
erjo@1850
|
868 }
|
erjo@1850
|
869 open(LS, "ls -1 $confdir/$driver/ |") or
|
erjo@1850
|
870 die "couldn't open $confdir/$driver: $!";
|
erjo@1850
|
871
|
erjo@1850
|
872 while (my $f = <LS>) {
|
erjo@1850
|
873 chomp($f);
|
erjo@1850
|
874 if ($f =~ /\.([[:xdigit:]]+)\.conf$/) {
|
erjo@1850
|
875 if (stat("$confdir/$driver/$devid.$1.conf")) {
|
erjo@1850
|
876 printf "Driver '$driver' is already used for '$devid'\n";
|
erjo@1850
|
877 $done = 1;
|
erjo@1850
|
878 last;
|
erjo@1850
|
879 }
|
erjo@1850
|
880 if (symlink("$f", "$confdir/$driver/$devid.$1.conf")) {
|
erjo@1850
|
881 printf "WARNING: Driver '$driver' will be used for '$devid'\n" .
|
erjo@1850
|
882 "This is safe _only_ if driver $driver is meant for " .
|
erjo@1850
|
883 "chip in device $devid\n";
|
erjo@1850
|
884 $done = 1;
|
erjo@1850
|
885 last;
|
erjo@1850
|
886 } else {
|
erjo@1850
|
887 warn "couldn't create symlink for \"$f\": $! -\n" .
|
erjo@1850
|
888 "installation may be incomplete\n";
|
erjo@1850
|
889 }
|
erjo@1850
|
890 }
|
erjo@1850
|
891 }
|
erjo@1850
|
892 close(LS);
|
erjo@1850
|
893 if ($done == 0) {
|
erjo@1850
|
894 printf "driver '$driver' is not installed (properly)!\n";
|
erjo@1850
|
895 return 1;
|
erjo@1850
|
896 }
|
erjo@1850
|
897 return 0;
|
erjo@1850
|
898 }
|
erjo@1850
|
899
|
erjo@1850
|
900 sub list_drivers {
|
erjo@1850
|
901 my $cards = get_cards();
|
erjo@1850
|
902 open(LS, "/bin/ls -1 $confdir|") or die "couldn't open $confdir: $!";
|
erjo@1850
|
903 while (my $driver = <LS>) {
|
erjo@1910
|
904 chomp($driver);
|
erjo@1910
|
905 if (-e "$confdir/$driver") {
|
erjo@1910
|
906 printf "%s : %s\n", $driver, install_status($cards, $driver);
|
erjo@1910
|
907 }
|
erjo@1850
|
908 }
|
erjo@1850
|
909 close(LS);
|
erjo@1850
|
910 return 0;
|
erjo@1850
|
911 }
|
erjo@1850
|
912
|
erjo@1850
|
913
|
erjo@1850
|
914 sub get_cards {
|
erjo@1850
|
915 #01:00.0 Class 0300: 1002:4c66 (rev 01)
|
erjo@1850
|
916 # Subsystem: 1043:1732
|
erjo@1850
|
917 my @cards = ();
|
erjo@1850
|
918 if (open(LSPCI, "/usr/bin/lspci -vn|")) {
|
erjo@1850
|
919 my $card;
|
erjo@1850
|
920 while (my $line = <LSPCI>) {
|
erjo@1850
|
921 if ($line =~ /^[0-9a-f]+.+\s$re_dev_id:$re_dev_id/) {
|
erjo@1850
|
922 $card = {vendor => uc($1), device => uc($2)};
|
erjo@1850
|
923 printf DBG "card: %s, %s\n", $1, $2;
|
erjo@1850
|
924 } elsif ($line =~ /.+Subsystem:\s$re_dev_id:$re_dev_id/) {
|
erjo@1850
|
925 $card->{subvendor} = uc($1);
|
erjo@1850
|
926 $card->{subdevice} = uc($2);
|
erjo@1850
|
927 printf DBG "sub: %s, %s\n", $1, $2;
|
erjo@1850
|
928 push(@cards, $card);
|
erjo@1850
|
929 }
|
erjo@1850
|
930 }
|
erjo@1850
|
931 close(LSPCI);
|
erjo@1850
|
932 }
|
erjo@1850
|
933
|
erjo@1850
|
934 if (open(LSUSB, "lsusb |")) {
|
erjo@1850
|
935 my $card;
|
erjo@1850
|
936 while (my $line = <LSUSB>) {
|
erjo@1850
|
937 if ($line =~ /.+: ID\s$re_dev_id:$re_dev_id/) {
|
erjo@1850
|
938 $card = {vendor => uc($1), device => uc($2)};
|
erjo@1850
|
939 push(@cards, $card);
|
erjo@1850
|
940 }
|
erjo@1850
|
941 }
|
erjo@1850
|
942 close(LSUSB);
|
erjo@1850
|
943 }
|
erjo@1850
|
944 return \@cards;
|
erjo@1850
|
945 }
|
erjo@1850
|
946
|
erjo@1850
|
947 sub install_status {
|
erjo@1850
|
948 my ($cards, $driver) = @_;
|
erjo@1850
|
949
|
erjo@1850
|
950 if (!$cards or !$driver) {
|
erjo@1850
|
951 return;
|
erjo@1850
|
952 }
|
erjo@1850
|
953
|
erjo@1850
|
954 my ($sys, $conf, $inf);
|
erjo@1850
|
955 my ($vendor, $device, $subvendor, $subdevice, $busid, $ret);
|
erjo@1850
|
956
|
erjo@1850
|
957 $sys = $conf = $inf = 0;
|
erjo@1850
|
958 open(LS2, "/bin/ls -1 $confdir/$driver|") or
|
erjo@1850
|
959 die "couldn't open $confdir/$driver: $!";
|
erjo@1850
|
960 while (my $file = <LS2>) {
|
erjo@1850
|
961 chomp($file);
|
erjo@1850
|
962 if ($file =~ /\.sys$/) {
|
erjo@1850
|
963 $sys = 1;
|
erjo@1850
|
964 } elsif ($file =~ /\.inf$/) {
|
erjo@1850
|
965 $inf = 1;
|
erjo@1850
|
966 } elsif ($file =~ /^$re_sub_dev_conf$/) {
|
erjo@1850
|
967 $busid = hex($5);
|
erjo@1850
|
968 $conf = 1 if ($busid eq $WRAP_PCI_BUS);
|
erjo@1850
|
969 } elsif ($file =~ /^$re_dev_conf$/) {
|
erjo@1850
|
970 $busid = hex($3);
|
erjo@1850
|
971 $conf = 1 if ($busid eq $WRAP_USB_BUS or $busid eq 0 or
|
erjo@1850
|
972 $busid eq $WRAP_PCI_BUS);
|
erjo@1850
|
973 }
|
erjo@1850
|
974 }
|
erjo@1850
|
975 close(LS2);
|
erjo@1850
|
976 printf DBG "status: $sys, $inf, $conf\n";
|
erjo@1850
|
977 if ($sys eq 0 or $inf eq 0 or $conf eq 0) {
|
erjo@1850
|
978 $ret = "invalid driver!";
|
erjo@1850
|
979 return $ret;
|
erjo@1850
|
980 }
|
erjo@1850
|
981 $ret = "driver installed";
|
erjo@1850
|
982 open(LS2, "/bin/ls -1 $confdir/$driver|") or
|
erjo@1850
|
983 die "couldn't open $confdir/$driver: $!";
|
erjo@1850
|
984
|
erjo@1850
|
985 while (my $file = <LS2>) {
|
erjo@1850
|
986 chomp($file);
|
erjo@1850
|
987 next if ($file !~ /\.conf$/);
|
erjo@1850
|
988 $conf = 0;
|
erjo@1850
|
989 if ($file =~ /^$re_sub_dev_conf$/) {
|
erjo@1850
|
990 ($vendor, $device, $subvendor, $subdevice, $busid) =
|
erjo@1850
|
991 (uc($1), uc($2), uc($3), uc($4), hex($5));
|
erjo@1850
|
992 $conf = 1;
|
erjo@1850
|
993 foreach my $card (@{$cards}) {
|
erjo@1850
|
994 if ($card->{vendor} eq $vendor and
|
erjo@1850
|
995 $card->{device} eq $device and
|
erjo@1850
|
996 $card->{subvendor} eq $subvendor and
|
erjo@1850
|
997 $card->{subdevice} eq $subdevice and
|
erjo@1850
|
998 $busid eq $WRAP_PCI_BUS) {
|
erjo@2293
|
999 $ret .= " : device ($vendor:$device" .
|
erjo@1850
|
1000 ":$subvendor:$subdevice) present";
|
erjo@1850
|
1001 $conf = 2;
|
erjo@1850
|
1002 last;
|
erjo@1850
|
1003 }
|
erjo@1850
|
1004 }
|
erjo@1850
|
1005 } elsif ($file =~ /^$re_dev_conf/) {
|
erjo@1850
|
1006 ($vendor, $device, $subvendor, $subdevice, $busid) =
|
erjo@1850
|
1007 (uc($1), uc($2), "\\*", "\\*", hex($3));
|
erjo@1850
|
1008 $conf = 1;
|
erjo@1850
|
1009 foreach my $card (@{$cards}) {
|
erjo@1850
|
1010 if ($card->{vendor} eq $vendor and
|
erjo@1850
|
1011 $card->{device} eq $device and
|
erjo@1850
|
1012 ($busid eq $WRAP_USB_BUS or $busid eq 0 or
|
erjo@1850
|
1013 $busid eq $WRAP_PCI_BUS)) {
|
erjo@2293
|
1014 $ret .= " : device ($vendor:$device) present";
|
erjo@1850
|
1015 $conf = 2;
|
erjo@1850
|
1016 last;
|
erjo@1850
|
1017 }
|
erjo@1850
|
1018 }
|
erjo@1850
|
1019 }
|
erjo@1850
|
1020 next if ($conf le 1);
|
erjo@1850
|
1021 # find if kernel knows of an alternate driver for this device
|
erjo@1850
|
1022 my $devstring;
|
erjo@1850
|
1023 if ($busid eq $WRAP_USB_BUS or $busid eq 0) {
|
erjo@1850
|
1024 $devstring = sprintf("usb:v%sp%sd", $vendor, $device);
|
erjo@1850
|
1025 } elsif ($busid eq $WRAP_PCI_BUS) {
|
erjo@1850
|
1026 $devstring = sprintf("pci:v0000%sd0000%ssv", $vendor, $device);
|
erjo@1850
|
1027 } else {
|
erjo@1850
|
1028 next;
|
erjo@1850
|
1029 }
|
erjo@1850
|
1030 open(MODPROBE, "modprobe -c|") or next;
|
erjo@1850
|
1031 while (my $line = <MODPROBE>) {
|
erjo@1850
|
1032 my $alt;
|
erjo@1850
|
1033 chomp($line);
|
erjo@1850
|
1034 next if $line !~ /$devstring/;
|
erjo@1850
|
1035 $alt = (split(' ', $line))[-1];
|
erjo@1850
|
1036 chomp($alt);
|
erjo@1850
|
1037 if (length($alt) gt 0 and $alt ne "ndiswrapper") {
|
erjo@1850
|
1038 $ret .= " (alternate driver: $alt)";
|
erjo@1850
|
1039 last;
|
erjo@1850
|
1040 }
|
erjo@1850
|
1041 }
|
erjo@1850
|
1042 close(MODPROBE);
|
erjo@1850
|
1043 }
|
erjo@1850
|
1044 close(LS2);
|
erjo@1850
|
1045 printf DBG "driver: $driver, $ret\n";
|
erjo@1850
|
1046 return $ret;
|
erjo@1850
|
1047 }
|
erjo@1850
|
1048
|
erjo@1850
|
1049 ## Local Variables: ##
|
erjo@1850
|
1050 ## cperl-indent-level: 4 ##
|
erjo@1850
|
1051 ## End: ##
|