#!/usr/bin/perl # (C) 2011-2013 Pavel Polyakov our $devd_usb='/var/run/usb-%s'; our $verbose=0; our $D=0; ##### #$v4l='/var/run/v4l'; # for uvcdynctl %PROD = ( '0x046d:0x0802' => 'c200', # P/N 860-000206; V-U0011 http://logitech-en-amr.custhelp.com/app/answers/detail/a_id/20390/kw/c200 '0x046d:0x080f' => 'c120', # P/N 860-000237; V-U0012 http://logitech-en-amr.custhelp.com/app/answers/detail/a_id/20368/kw/c120 '0x046d:0x0819' => 'c210', # P/N 860-000272; V-U0019 '0x046d:0x081a' => 'c525', # P/N 960-000722; V-U0023; HD 720p http://logitech-en-amr.custhelp.com/app/answers/detail/a_id/23679/kw/c525 '0x046d:0x081b' => 'c310', # P/N 860-000???; V-U0015; HD 720p http://logitech-en-amr.custhelp.com/app/answers/detail/a_id/17181/kw/c310 '0x046d:0x081d' => 'c510', # P/N 860-000261; V-U0016; HD 720p http://logitech-en-amr.custhelp.com/app/answers/detail/a_id/17551/kw/c510 '0x046d:0xbeef' => 'beef', # P/N 860-000261; V-U0016; HD 720p -> BEEF '0x046d:0x0821' => 'c910', # P/N 860-000???; V-U0017; HD 1080p http://logitech-en-amr.custhelp.com/app/answers/detail/a_id/17516/kw/c910 '0x04fc:0x0171' => 'md80-disk', # sunplus md80-disk '0x04fc:0x1528' => 'md80-1528', # sunplus md80-1528 '0x0ac8:0x3450' => 'ms155', # BRAVIS (foxtrot) Vimicro-ms '0x1e4e:0x0102' => 'vm305', # Startex VM 305 (ATB) 60 uah = ACB-C028 Etron '0x1e4e:0x0109' => 'sven-ic350',# Sven IC-350 (Eldorado); usb-mic = Etron Technology, Inc. '0x1871:0x0316' => 'vm305b', # Startex VM 305 (ATB) 69? uah = ACB-C028 AVEO '0x1871:0x0306' => 'vm305c', # Startex VM 305 (ATB) 69? uah = ACB-C028 AVEO-my '0x1871:0x0141' => 'sven-ic300',# Sven IC-300 (Eldorado) ball; usb-mic = AVEO '0x093a:0x2700' => '413g', # CANYON CNR-WCAM413G 8717371 848378 '0x067b:0x2303' => 'PL-2303', # Viewcon первый что купил, с большим комом '0x058f:0x5608' => 'endoscope-7mm', # 2m 7mm '0x058f:0x6254' => 'hub gmb UHB-C244', # 4-port hub (gray) '0x05e3:0x6254' => 'hub usb3.0 7port', # 7-port hub on/off '0x0781:0x9292' => 'SanDisk ImageMate CF', # P/N 20-60-00134; SDDR-92 '0x0e8d:0x0002' => 'MediaTek Texet', # MediaTek Inc MT6235 - texet 510R '0x13fe:0x3800' => 'Patriot 16GB', # quad-channel '0x1a2c:0x0002' => 'kbd-startex', # startex (ATB) keyboard '0x1410:0x2110' => 'u720', # Sprint Novatel Wireless Ovation U720; 3G CDMA '0x19d2:0x0001' => 'MF620', # zte1 = Life:) ZTE MF620, Qualcomm '0x12d1:0x1001' => 'E1550', # Huawei '0x12d1:0x140c' => 'E173', # Huawei '0x1a40:0x0101' => 'Viewcon VE056 5m', # active extension '0x0bda:0x2838' => 'RTL2838UHIDIR', # RTL-SDR '0x0079:0x0006' => 'joy-startex', # Microntek USB Joystick / ATB '0x0581:0x0101' => 'ums-startex', # Microntek USB Joystick / ATB '0x1997:0x2433' => 'kbd-rii8', # Mini Keyboard (no backlight) ); $pat=qr'vendor (0x046d|0x058f|0x0781|0x0ac8|0x13fe|0x19d2|0x1a40|0x1e4e|0x1871|0x0bda)|ZTE CDMA|HUAWEI|Novatel|USB-Serial|Etron Technology|Keykoard|SanDisk|Sunplus|Vimicro|AVEO Technology|PixArt Imaging|Patriot|MediaTek|Alcor|Camera|Serial|RTL2838|Microntek|Joystick|Keyboard|0x0581'i; our $reUCOM=qr/(u(?:pl|ch|vs|sl)?com|u3g|uftdi|umodem)/; %CAMERA = ( '0B4BEC60' => 'c1', # c120 'B700EC60' => 'c7', # c120 M12 '8E40EC60' => 'c5', # c120 '24B33F60' => 'c8', # c200 '6DB73F60' => 'c2', # c200 (лежала за телеком) '424452D0' => 'c4:k1', # c210 knysh 'B0E5F790' => 'i1:c9', # c510 isotov '135AA2B0' => 'c9', # c510 my 4900000849374 '0300079871' => 'CF1', # SanDisk ImageMate CF ReaderWriter N0006413 '07B10501655B8431' => 'Patriot16-my1', # my1 '07B21101654FA385' => 'Patriot16-my2', # my2 '531991305941930' => 'Texet-510R-my', '16052900' => 'sdr16052900', '16070301' => 'sdr16070301', '16070302' => 'sdr16070302', ); #print STDERR "cam list:\n". join("\n",@LIST); my $RTL_SDR=0; sub new_camera($) { # nickname; all info from global vars my $nick=shift; open(O,">","/var/run/$nick") && do { print O $ugen; close O; }; if ($nick=~/^sdr\d+/) { open(O,">","/var/run/$nick.index") && do { print O $RTL_SDR++; close O; }; }; return sprintf("\t%-20s \@$ugen; product $vendor:$product ($name) serial = $serial\n", $nick); } our %dev_seen=(); sub next_dev($){ my $dev=shift; for(0..9){ my $n="$dev-$_"; if(!defined $dev_seen{$n}) { $dev_seen{$n}=1; return $n; } } return undef; } sub symlink1($$;$$){ # src,dest; force; prefix my($src,$dest,$force,$comment)=@_; my $devdest="/dev/$dest"; my $prefix=''; if($src eq $dest) { # print STDERR "!! $src == $dest\n"; $prefix="# == "; } elsif(!defined $dev_seen{$devdest}){ $dev_seen{$devdest}=$src; unlink $devdest; symlink $src, $devdest; } else { print STDERR "!! DUP! $src to $dest\n"; } if($verbose>2){ $comment="\t# $comment" if defined $comment; $force=' ' unless defined $force; print "${prefix}ln -s$force $src $devdest$comment\n"; } } our $ugen; our $ifdrvs=''; sub usb_serial(){ my $devname=''; my @CUA=(); $name="$vendor:$product" if $name eq ''; print STDERR qq%ugen$ugen: id=$id serial="$serial" name="$name" nickname="$nickname"\n% if $verbose>0; #my $name1=next_dev $name; # numbered alias print STDERR "\tSERIAL: $ifdrvs ($vendor:$product $name)\n"; my $re_stats=qr'\.2$'; # stats/control port if($name=~/E173/) { $re_stats=qr'\.3$'; } for $dev (split/ +/,$ifdrvs) { if($dev=~/^$reUCOM(\d)$/) { ($devname,$devnum)=($1,$2); #if($dev=~/^u(pl)?com|^u3g/) { $devname=$dev }; #print "dev:$dev\n"; #open(I,"<",sprintf($devd_usb,$dev)) && do{ # while(){ # chomp; # if(/^cuaU|^ttyU/){ # push @CUA,$_; # } # } # close I; #}; #my $devname1=next_dev $devname; # numbered driver name my $devname1="$devname$devnum"; # driver device name print STDERR "\tdev:$dev devname1:$devname1 devname:$devname devnum:$devnum nickname:$nickname\n" if $D>2; #my $re_main1=qr'\.0$'; # main/modem port #if($devname=~/^u(pl)?com/) { $re_main1=qr/^cuaU\d$/ }; my %U=(); my @ALIASES=( $devname1, $devname ); push @ALIASES, $nickname unless $nickname=~/^ugen|^$/; open(I, '-|', "sysctl dev.$devname.$devnum") && do { print STDERR "---- sysctl dev.$devname.$devnum\n"; while() { next if /\%(driver|desc)/; print STDERR "\t$_" if $D>2; if(/\.(ttyports|ttyname|\%parent|\%location|\%pnpinfo):\s*(.+)$/) { print STDERR "$1 = $2\n" if $D>2; $U{$1}=$2; } if(/\.(\%location|\%pnpinfo):\s*(.+)$/) { my $parm=$2; while($parm=~/\s*([a-z]+)=(\S+)\s*/gc) { print STDERR "$1 = $2\n" if $D>5; $U{$1}=$2; } } } close I; }; if(defined $U{bus}) { push @ALIASES,"$devname\@bus$U{bus}"; push @ALIASES,"$nickname\@bus$U{bus}" unless $nickname eq ''; } if(defined $U{bus} && defined $U{hubaddr} && defined $U{port}) { push @ALIASES,"$devname\@bus$U{bus}\@hub$U{hubaddr}\@port$U{port}"; push @ALIASES,"$devname\@hub$U{hubaddr}\@port$U{port}"; push @ALIASES,"$devname\@port$U{port}"; push @ALIASES,"$nickname\@bus$U{bus}\@hub$U{hubaddr}\@port$U{port}" unless $nickname eq ''; push @ALIASES,"$nickname\@hub$U{hubaddr}\@port$U{port}" unless $nickname eq ''; push @ALIASES,"$nickname\@port$U{port}" unless $nickname eq ''; } print STDERR "\tAliases: ",join(' ',@ALIASES), "\n"; for my $alias (@ALIASES){ my $portname="cua$U{ttyname}"; for (my $num=0; $num<$U{ttyports}; $num++){ my $portsuff=$U{ttyports}>1 ? ".$num" : ''; #$portname.=$portsuff; #my($sym)=($_); #$sym=~s/^cuaU\d+/\%s/; #$sym=~s/^ttyU\d+/\%s-tty/; my $port1="$portname$portsuff"; my $sym1="$alias$portsuff"; next if !-e "/dev/$port1"; printf "$portname\t$port1\t%-30s\n", $sym1 if $D>2; #$alt=undef; #if(/$re_main1/) { $alt='' } #elsif(/$re_stats/) { $alt=".stats" }; #my $alt1= defined $alt ? "$name1$alt" : ''; #printf "\t\t$_\t$sym \t$sym\t$alt1\n", $devname1, $name1 if !/init|lock|tty/; for my $part ('','.init','.lock') { #next unless defined $src; #$dest1=sprintf $sym, $src; # named dest symlink1 $port1.$part, $sym1.$part, 'f'; #print "ln -s $_ /dev/$dest1\n"; #if(defined $alt && !/tty/) { # #if($dest1 ne $alt) { # symlink1 $dest1,"$src$alt",'f','default'; # #} # # my $dest0=$src; $dest0=~s/-\d+$//; # for $alt1( '', $alt ) { # $dest1=$dest0.$alt1; # if( !defined $dev_seen{$dest1} ){ # #print STDERR "$src$alt1 --> $dest1 $dev_seen{$dest1}\n"; # symlink1 "$src$alt1",$dest1, undef,'short'; # $dev_seen{$dest1}=1; # }} # } } }} } } } our $need=0; sub finish1(){ if($need) { chomp $out; $out.=" \t// $ifdrvs\n"; print STDERR $out2; print $out; } $out2=''; $out=''; if($ifdrvs=~/u(pl|ch|vs|sl)?com|u3g|uftdi|umodem/) { usb_serial(); } #### clear for next $prev=$ugen; $ifdrvs=''; $need=0; } while($arg=shift @ARGV) { if($cnt = $arg=~s/[d]//g) { # $D+=$cnt; } elsif($cnt = $arg=~s/[v]//g) { # $verbose+=$cnt; } elsif($cnt = $arg=~s/[d]//g) { # $D+=$cnt; } } @LIST=`usbconfig show_ifdrv`; chomp(@LIST); push @LIST,undef; $out=''; $out2=''; $prev=''; for $cam (@LIST) { print STDERR "\n\n\n------- $cam\n" if $verbose>0; if(!defined $cam) { #finish1(); last; }; #print STDERR "usbdev: $cam\n"; #print STDERR "cam: $cam\n"; $ugen='???'; if($cam=~ /^ugen([\d.]+): (?:(\S+): )?1; my @DATA=`usbconfig -d $ugen dump_device_desc show_ifdrv`; $serial=''; $product=''; $vendor=''; for $data (@DATA){ #print $data; if($data=~/iSerialNumber =.+? <([0-9 a-z]+)>/i) { $serial=$1; }; if($data=~/idProduct =.+?([0-9a-z]+)/i) { $product=$1; }; if($data=~/idVendor =.+?([0-9a-z]+)/i) { $vendor=$1; }; } $id="$vendor:$product"; $name=$PROD{$id}; $nickname=$CAMERA{$serial}; $nickname=$name unless defined $nickname; print STDERR qq%ugen$ugen: id=$id serial="$serial" name="$name" nickname="$nickname"\n%; if($nickname ne '') { for(split/:/,$nickname) { #$out.=new_camera($_); print new_camera($_); } } } else { } print STDERR "ifdrvs='$ifdrvs' \n" if $verbose>0; if($ifdrvs=~$reUCOM) { print STDERR qq%ugen$ugen: id=$id serial="$serial" name="$name" nickname="$nickname"\n%; usb_serial(); } } else { print STDERR "??? $cam\n"; } } system "mkdir -p /tmp/sys/class/video4linux; ln -s /tmp/sys/class /sys"; __END__ iSerialNumber = 0x0002 <24B33F60> iManufacturer = 0x0001 iProduct = 0x0002 iSerialNumber = 0x0000