File modeswitch.conf2udevrules.pl of Package usb_modeswitch

#!/usr/bin/perl -w
#
# This script creates udev rules from a usb_modeswitch.conf file. call with
# ./modeswitch.conf2udevrules.pl usb_modeswitch.conf > udev.rules, then double
# check the generated udev rules!
#
# you can add the devices which should be ignored (probably because they are
# handled by a different program) to @ignore, devices that need special udev
# rules can be added to print_custom().
#
# (C) 2009 Novell, Inc. Author: Stefan Seyfried, seife@suse.de
#
# This program is released under the GPL v2 or, at your option, any later version.

@ignore = ( # [ vendor, product ], set product to 0 to blacklist a whole vendor.
	[ 0x05c6, 0x1000 ], # lots of devices have this ID, all with different parameters :(
	[ 0x0af0, 0x6711 ], # those are all option devices handled by "ozerocdoff"
	[ 0x0af0, 0x6731 ], # maybe we should just blacklist all option devices?
	[ 0x0af0, 0x6751 ],
	[ 0x0af0, 0x6771 ],
	[ 0x0af0, 0x6791 ],
	[ 0x0af0, 0x6811 ],
	[ 0x0af0, 0x6911 ],
	[ 0x0af0, 0x6951 ],
	[ 0x0af0, 0x6971 ],
	[ 0x0af0, 0x7011 ],
	[ 0x0af0, 0x7031 ],
	[ 0x0af0, 0x7051 ],
	[ 0x0af0, 0x7071 ],
	[ 0x0af0, 0x7111 ],
	[ 0x0af0, 0x7211 ],
	[ 0x0af0, 0x7251 ],
	[ 0x0af0, 0x7271 ],
	[ 0x0af0, 0x7301 ],
	[ 0x0af0, 0x7311 ],
	[ 0x0af0, 0x7361 ],
	[ 0x0af0, 0x7401 ],
	[ 0x0af0, 0x7501 ],
	[ 0x0af0, 0x7601 ],
	[ 0x0af0, 0xc031 ],
	[ 0x0af0, 0xd031 ],
	[ 0x0af0, 0xd033 ],
	[ 0x1199, 0x0000 ], # the sierra driver handles sierra devices by itself AFAIK
	[ 0x1410, 0x5010 ], # novatel mc950d is handled in print_custom()
	[ 0x19d2, 0x2000 ], # many different configs in the config file, cannot know which one to take
	[ 0, 0 ] # terminate the array.
);

sub checkbl(@)
{
	$v = hex("0x" . $_[0]);
	$p = hex("0x" . $_[1]);
	# printf(STDERR "checking 0x%04x:0x%04x\n", $v, $p);
	for ($i = 0; $ignore[$i][0] != 0; $i++)
	{
		if ($ignore[$i][0] == $v) {
			if (($ignore[$i][1] == 0) || # wildcard
			    ($ignore[$i][1] == $p)) {
				printf(STDERR "ignoring device %04x:%04x, bl entry %2d (%04x:%04x)\n",
					$v, $p, $i, $ignore[$i][0], $ignore[$i][1]);
				return 1;
			}
		}
	}
	return 0;
}

sub print_head()
{
	print("ACTION!=\"add\", GOTO=\"usb_modeswitch_end\"\n");
	print("\n");
	print("# this udev rules file is autogenerated by modeswitch.conf2udevrules.pl\n");
	print("# which can be found in the usb_modeswitch package\n");
	print("\n");
}

sub print_foot()
{
	print("\n");
	print("LABEL=\"usb_modeswitch_end\"\n");
}

sub print_custom()
{
	print("# devices that need custom rules\n");
	# novatel mc950d, has two different entries in usb_modeswitch.conf, but works also with plain "eject"
	print("SUBSYSTEM==\"block\", SYSFS{idProduct}==\"5010\", SYSFS{idVendor}==\"1410\", RUN=\"/bin/eject %k\"\n");
}

$count = 0;
$ignored = 0;
$failed = 0;
$flag = 0;
$dup = 0;

print_head;
while ($line = <>)
{
	if ($line =~ m/^(#|$)/) {
		next;
	}

	if ($line =~ m/^;*DefaultVendor=\s*0[Xx](.*?)[;\s]*$/) {
		if ($flag) {
			# a new record starts, but the old one is not finished.
			print(STDERR "ignored entry (not all required fields): flag: $flag vendor: $vendor id: $product\n");
			$failed++;
		}
		$flag = 1; # reset flag
		$vendor = $1;
	}
	if (! $flag) {
		next;
	}
	if ($line =~ m/^;*DefaultProduct=\s*0[Xx](.*?)[;\s]*$/) {
		$product = $1;
		$flag |= 2;
	}
	if ($line =~ m/^;*MessageEndpoint=\s*0[Xx](.*?)[;\s]*$/) {
		$endpoint = $1;
		$flag |= 4;
	}
	if ($line =~ m/^;*MessageContent=.*(".*")/) {
		$message = $1;
		$flag |= 8;
	}
	if ($flag == 0x0f) {
		if (checkbl($vendor, $product)) {
			$ignored++;
		} elsif (defined($found{$vendor}{$product})) {
			printf(STDERR "duplicate entry: %s:%s\n", $vendor, $product);
			if (($found{$vendor}{$product}[0] ne $endpoint) ||
			    ($found{$vendor}{$product}[1] ne $message)) {
				printf(STDERR "input line: $.\n");
				printf(STDERR "...with different endpoint or message. Aborting!\n");
				printf(STDERR "old endpoint: '%s'  old message: '%s'\n", $found{$vendor}{$product}[0], $found{$vendor}{$product}[1]);
				printf(STDERR "new endpoint: '%s'  new message: '%s'\n", $endpoint, $message);
				exit 1;
			}
			$dup++;
		} else {
			printf("SUBSYSTEM==\"usb\", ATTRS{idVendor}==\"%s\", ATTRS{idProduct}==\"%s\"," .
			       " RUN+=/usr/sbin/usb_modeswitch -v 0x%s -p 0x%s -m 0x%s -M %s\n",
			       $vendor, $product, $vendor, $product, $endpoint, $message);
			$found{$vendor}{$product}[0] = $endpoint;
			$found{$vendor}{$product}[1] = $message;
			$count++;
		}
		$flag = 0;
	}
}
print_custom;
print_foot;

printf(STDERR "Summary:\n");
printf(STDERR "  total udev lines from config:  %d\n" .
	      "  ignored devices (blacklisted): %d\n" .
	      "  ignored devices (malformed):   %d\n" .
	      "  ignored devices (duplicates):  %d\n",
	      $count, $ignored, $failed, $dup);
openSUSE Build Service is sponsored by