diff --git a/hp2101nw_connect.pl b/hp2101nw_connect.pl index d05ab490674390767aae3c2eba02ec649da060ca..3c0b5cd082ccf1f2e452b35b7de522195e6530e1 100755 --- a/hp2101nw_connect.pl +++ b/hp2101nw_connect.pl @@ -32,7 +32,10 @@ use strict; our $debug=1; -our $VERSION=0.01; +our $VERSION = 0.01; +# Wait a maximum of 5 seconds for data: +our $SOCK_TIMEOUT = 5; + print "hp2101nw_connect.pl - version $VERSION\n"; print "Linux connection utility for the HP 2101nw wireless G USB print server.\n\n"; print "(C) 2012 Reinhold Kainhofer <reinhold\@kainhofer.com>\n"; @@ -157,6 +160,38 @@ sub ask_input ($$$) { return $retval; } +############################################################################### +## DEVICE CONFIGURATION HANDLING +############################################################################### + + +sub config_parse ($) { + my $cfg = shift; + my @entries = split ('\n', $cfg); + my @config = (); + foreach (@entries) { + my $key = substr ($_, 0, 4); + (my $name, my $value) = split (/:/, substr ($_, 5), 2); + push (@config, [$key, $name, $value]); + } + return @config; +} + +# Convert a list of the form [ ["OPTIONID", "OPTIONNAME", VALUE], ...] +# into a string to be sent to the device +sub config_create ($) { + my $cfg = shift; + my $result = ""; + foreach my $o (@$cfg) { + if ($o->[0] && length($o->[0])>0) { + $result .= sprintf ("%s %s:%s\n", $o->[0], $o->[1], $o->[2]); + } else { + $result .= sprintf ("%s:%s\n", $o->[1], $o->[2]); + } + } + return $result; +} + ######################## # validation functions @@ -180,601 +215,231 @@ sub is_hostname ($) { -############################################################################### -## USB DEVICE MANAGEMENT / COMMUNICATION FUNCTIONS -############################################################################### - -sub setup_ports () { -# my $io_information = IO::Socket::INET->new(LocalPort => $port_information, -# Proto => "udp"); -# my $io_sbsu = IO::Socket::INET->new(LocalPort => $port_command, -# Proto => "udp"); -# +sub config_parse ($) { + my $cfg = shift; + my @entries = split ('\n', $cfg); + my @config = (); + foreach (@entries) { + my $key = substr ($_, 0, 4); + (my $name, my $value) = split (/:/, substr ($_, 5), 2); + push (@config, [$key, $name, $value]); + } + return @config; } -sub SBSU_create_buffer ($) { - my $cmd = shift; - return sprintf ("SBSU%s", pack("v", $cmd)); +# Convert a list of the form [ ["OPTIONID", "OPTIONNAME", VALUE], ...] +# into a string to be sent to the device +sub config_create ($) { + my $cfg = shift; + my $result = ""; + foreach my $o (@$cfg) { + if ($o->[0] && length($o->[0])>0) { + $result .= sprintf ("%s %s:%s\n", $o->[0], $o->[1], $o->[2]); + } else { + $result .= sprintf ("%s:%s\n", $o->[1], $o->[2]); + } + } + return $result; } -# Read data into the second argument (output argument!), return -# size of data -sub SBSU_receive_data ($$$) { - my $sock = shift; - my $cmd = shift; -} -sub SBSU_status_parse ($) { +############################################################################### +## USB DEVICE MANAGEMENT / COMMUNICATION FUNCTIONS +############################################################################### +sub net_send_data ($$) { + my $sock = shift; + my $data = shift; + return $sock->send($data, 0) + or print "Error sending data to socket $sock. Data was:\n$data\n"; } -sub device_detect () { - my $request = SBSU_create_buffer ($SBSU_STATUS); - my @result = (); - my $loop = 0; - debug "Sending device detection request (UDP broadcast on port 34447)\n"; - my $br_addr = sockaddr_in ($port_command, INADDR_BROADCAST); - - my $broadcast = IO::Socket::INET->new ( - PeerPort => $port_command, -# PeerAddr => inet_ntoa(INADDR_BROADCAST), - Proto => 'udp', -# Listen => 1, - Broadcast => 1 ) - or die "Can't bind broadcast socket: $@\n"; - my $sel = IO::Select->new( $broadcast ); +sub net_read_data ($) { + my $sock = shift; + my $sel = IO::Select->new( $sock ); + my $data = undef; - while (++$loop <= 5 && scalar(@result) < 5) { - print "."; - $broadcast->send( $request, 0, $br_addr ) - or die "Error at sending: $!\n"; - while ($sel->can_read (1)) { - my $data=""; - $broadcast->recv ($data, 8096); - push @result, $data; - } + if ($sel->can_read ($SOCK_TIMEOUT)) { + $sock->recv ($data, 10240); +# # printf "net_read_data: %d bytes read\n", $len; + return $data; + } else { + debug "Unable to read data from socket $sock.\n"; + return $data; } - print "\nResult: @result\n"; - return @result; } -sub device_info ($) { - my $ip = shift (); - +sub SBSU_create_buffer ($) { + my $cmd = shift; + return sprintf ("SBSU%s", pack("v", $cmd)); } -sub create_status_request () { -} +# Read data into the second argument (output argument!), return +# size of data +sub SBSU_receive_data ($$$) { + my $sock = shift; + my $cmd = shift; -sub device_open ($) { - my $dev = shift; - my $res = $dev->open; - if ($res<0) { - printf "ERROR opening device (%d): %s\n", $res, $!; - } - $res = $dev->detach_kernel_driver_np(0); - # No error check, Linux always gives an error! - $res = $dev->set_configuration(1); - if ($res<0) { - printf "ERROR setting configuration 1 (%d): %s\n", $res, $!; - } - $res = $dev->claim_interface(0); - if ($res<0) { - printf "ERROR claiming interface 0 (%d): %s\n", $res, $!; - } } -sub device_close ($) { +sub info_data_write ($$) { my $dev = shift; - $dev->release_interface(0); - $dev->reset; -} - - + my $cfg = shift; -sub bulk_data_write ($$$) { - my $dev = shift; - my $data = shift; - my $len = shift; - # Add the header (12 bytes): '@\0', packet length, boxname (="XXXXXXXX") - my $request = sprintf ("@\0%s%s%s", pack ("v", $len), $thisboxname, $data); - debug "Request: $request\n"; - my $res = $dev->bulk_write (1, $request, length($request), 500); - if ($res<0) { - printf "ERROR write bulk data (%d): %s\n", $res, $!; - } - return $res; + my $sock = $dev->{'socket-info'}; + my $cfgstring = config_create ($cfg); + my $len = length ($cfgstring); + # Add the header (12 bytes): '@\0', packet length, boxname + my $request = sprintf ("@\0%s%s%s", pack ("v", $len), $dev->{'device-name'}, $cfgstring); + return net_send_data ($sock, $request); } # Read USB bulk data into the second argument (output argument!), return # size of data -sub bulk_data_read ($$$) { +sub info_data_read ($) { my $dev = shift; - # TODO: Get rid of the length argument, simply read all that is sent - # FIXME: Read bulk data in loops until there is nothing left to read? - my $len = $_[1]; - my $readdata = ""; - my $res = $dev->bulk_read (2, $readdata, $len+13, 500); - if ($res<0) { - printf "ERROR reading bulk data (%d): %s\n", $res, $!; - return; - } - if ($res == 0) { - debug "\tEmpty response received\n"; - return 0; - } - debug ("read %d bytes: \n%s\n\n", $res, $readdata); - # Check and cut off the header after some sanity checks: - if (substr ($readdata, 0, 3) ne "\@\0\0") { - printf "ERROR reading data: Wrong header %s\n", substr ($readdata, 0, 3); - } - my $datalen = unpack ("v", substr ($readdata, 3, 2)); - $res = $res-13; - if ($datalen != $res) { - printf "ERROR reading data: Expected %d bytes of data, got %d\n", $datalen, $res; - } - my $boxname = substr ($readdata, 5, 8); - # FIXME: Check the name of the box... - - # cut off the header: - $_[0]=substr ($readdata, 13); - return $res; -} - -sub device_reset ($) { - my $dev = shift; - progress "Resetting the device, please wait"; - my $res = bulk_data_write ($dev, "9002:\n", 6); - debug "\tSent 9002 reset command: %d\n", $res; - my $reset_done = 0; - # Poll the device until it doesn't respond. Then sleep for ~15 seconds - do { - my $readdata = ""; - $res = $dev->bulk_read (2, $readdata, 13, 100); - debug "\tData received: $readdata (len: $res)\n"; - sleep (1); - } while ($res > 0); - sleep_progress (20); - device_close ($dev); - progress "Device was reset. Please press Return."; - <STDIN>; -} - - -############################################################################### -## DEVICE CONFIGURATION HANDLING -############################################################################### + my $sock = $dev->{'socket-info'}; -sub print_current_configuration ($$) { - my $config = shift; - my $text = shift; - sub val ($$) { - my $config = shift; - my $var = shift; - foreach my $e (@$config) { - return $e->[2] if ($e->[0] eq $var); - } + my $data = net_read_data ($sock); + my $datalen = length ($data); + if (substr ($data, 0, 3) ne "@\0\0") { + printf "ERROR reading data: Wrong header '%s', expected @\\0\\0\n", substr ($data, 0, 3); return undef; } - progress $text; - printf "\tDevice name: %s\n", val($config, '0001'); - if (val($config,'0012') ne "Enable") { - printf "\tTCP/IP not yet configured and/or enabled.\n\n"; - return; - } - my $adhoc = val($config,'7024') == '1'; - if ($adhoc) { - # ad-hoc network: - my $sec = val($config,'7103'); - printf "\tWireless mode: Ad-hoc network\n"; - printf "\tSSID: %s\n", val($config,'7100'); - printf "\tChannel: %s\n", val($config,'7102'); - printf "\tSecurity: %s\n", security2string ($sec); - if ($sec == 0) { - # None => nothing to display - } elsif ($sec == 1) { - # WEP => Print passphrase - printf "\tWEP Key: %s\n", val($config,'7106'); - } else { - # WPA 1/2 or mixed - printf "\tEncryption: %s\n", encryption2string(val($config,'7118')); - printf "\tPassphrase: %s\n", val($config,'7119'); - } - } else { - # infrastructure network - my $sec = val($config,'7003'); - printf "\tSSID: %s\n", val($config,'7000'); - printf "\tChannel: %s\n", val($config,'7002'); - printf "\tSecurity: %s\n", security2string ($sec); - if ($sec == 0) { - # None => nothing to display - } elsif ($sec == 1) { - # WEP => Print passphrase - printf "\tAuthentication: %s\n", authentication2string(val($config,'7012')); - printf "\tWEP Key: %s\n", val($config,'7006'); - } else { - # WPA 1/2 or mixed - printf "\tEncryption: %s\n", encryption2string(val($config,'7018')); - printf "\tPassphrase: %s\n", val($config,'7019'); - } - } - - my $dhcp = (val($config,'4020') eq "Enable"); - printf "\tIPv4 method: %s\n", $dhcp?"DHCP":"manual"; - my $associated = val($config,'7014') =~ m/STATE:Associated/; - if ($associated || !$dhcp) { - printf "\tIP address: %s\n", val($config,'4000'); - printf "\tGateway: %s\n", val($config,'4001'); - printf "\tNetmask: %s\n", val($config,'4002'); - } - if ($associated) { - my $assinfo = val($config,'7014'); - printf "\tLink state: %s\n", $assinfo; - } else { - # Not connected - printf "\tWireless not connected\n"; + # data length as given in the header: + my $header_datalen = unpack ("v", substr ($data, 3, 2)); + $datalen = $datalen-13; # ignore 13 bytes header + if ($header_datalen != $datalen) { + printf "ERROR reading data: %d data bytes read, headers says %d bytes\n", $datalen, $header_datalen; + return undef; } - print "\n\n"; -} - - -sub device_config_request ($) { - my $dev = shift; - my $cfg = ""; - debug "Reading current configuration...\n"; - my $res = bulk_data_write ($dev, "9100:\n", 6); - $res = bulk_data_read ($dev, $cfg, 25600); - return $cfg; -} - -sub device_config_send ($$) { - my $dev = shift; - my $cfg = shift; - my $tmp = ""; - progress "Sending new configuation to the device. Please wait"; - debug "\tNew device config: %s\n", $cfg; - my $res = bulk_data_write ($dev, $cfg, length($cfg)); - sleep_progress (10); - # Now reset the device: - return device_reset ($dev); -} + my $boxname = substr ($data, 5, 8); + # FIXME: Check the name of the box... -sub config_parse ($) { - my $cfg = shift; - my @entries = split ('\n', $cfg); - my @config = (); - foreach (@entries) { - my $key = substr ($_, 0, 4); - (my $name, my $value) = split (/:/, substr ($_, 5), 2); - push (@config, [$key, $name, $value]); - } - return @config; + # cut off the header: + return substr ($data, 13); } -# Convert a list of the form [ ["OPTIONID", "OPTIONNAME", VALUE], ...] -# into a string to be sent to the device -sub config_create ($) { - my $cfg = shift; - my $result = ""; - foreach my $o (@$cfg) { - $result .= sprintf ("%s %s:%s\n", $o->[0], $o->[1], $o->[2]); - } - return $result; -} -sub set_hostname ($) { - my $dev = shift; - my $hostname = ask_input ("New hostname: ", \&is_hostname, - "\tA hostname can only contain A-Z, a-z, 0-9 and -, and may have 1 to 64 characters\n");; - my $config = config_create ([["0001", "BOX_NAME", $hostname]]); - debug "\tChanging hostname using config\n\t%s\n", $config; - return device_config_send ($dev, $config); -} -sub device_config_save ($$) { - my $filename = shift; - my $config = shift; - my $status = open FILE, ">$filename"; - if (!$status) { - printf "ERROR: %s\n", $!; - return; - } - print FILE $config; - progress "Current print server configuration saved to file '%s'\n", $filename; -} +sub SBSU_status_parse ($) { + my $data = shift; -sub device_config_restore ($$) { - my $dev = shift; - my $filename = shift; - my $status = open FILE, "<$filename"; - if (!$status) { - printf "ERROR: %s\n", $!; - return; + if (substr ($data, 0, 6) ne "SBSU\1\0") { + printf "ERROR reading data: Wrong header '%s', expected SBSU\\0\\1\n", substr ($data, 0, 6); + return undef; } - my $config = do { local $/; <FILE> }; - debug "Configuration file '%s' contains the data:\n", $filename, $config; - progress "Loaded configuration data from file '%s', sending it to the device.\n"; - return device_config_send ($dev, $config); -} + my $result = {}; + $result->{'data'} = $data; + # TODO: what does byte 6 mean? + my $devicename = substr ($data, 7, 8); + $result->{'device-name'} = $devicename; + $result->{'printer-name'} = substr ($data, 22, 64); + $result->{'locked-ip'} = substr ($data, 86, 16); # TODO: Shall we call inet_aton on the string here? + $result->{'locked-host'} = substr ($data, 102, 8); # TODO: 8 or 10 bytes + # TODO: Bytes 112-168 + $result->{'serial'} = unpack ("V", substr ($data, 168, 4)); + $result->{'vendor-id'} = unpack("v", substr ($data, 172, 2)); + $result->{'device-id'} = unpack("v", substr ($data, 174, 2)); -############################################################################### -## WIRELESS NETWORK DETECTION -############################################################################### - - -sub parse_survey_data ($) { - my $survey = shift; - my $networks = {}; - my @entries = split ("\x0b", $survey); - foreach (@entries) { - (my $ssid, my $settings) = split ("\x0c", $_); - my @settings = split (",", $settings); - $networks->{$ssid} = { - 'mac' => $settings[0], - 'channel' => $settings[1], - 'wifi_ver' => $settings[2], - 'secmode' => $settings[3], - 'signal' => $settings[4], - 'adhoc' => $settings[5] - }; - } - debug Dumper ($networks); - return $networks; -} - + $result->{'usb-descriptors'} = substr ($data, 176); -sub print_wireless_networks ($) { - my $aps = shift; - print "Detected wireless networks:\n"; - my $format = " %3s %-25s%-9s%-13s%-17s%-8s\n"; - printf $format, " ", "SSID", "Signal", "Security", "Type", "channel"; - print "\t------------------------------------------------------------------------\n"; - my $i = 0; - foreach my $ssid (sort {lc $a cmp lc $b} keys (%$aps)) { - ++$i; - my $network = $aps->{$ssid}; - printf $format, $i.")", $ssid, $network->{'signal'}, - security2string ($network->{'secmode'}), - $network->{'adhoc'}?"Ad-Hoc":"Infrastructure", - $network->{'channel'}; - } - print "\n"; + return $result; } +sub device_detect () { + my $request = SBSU_create_buffer ($SBSU_STATUS); + my $result = {}; + my $loop = 0; + debug "Sending device detection request (UDP broadcast on port 34447)\n"; + # I can't add the broadcast address to the IO::Socket::INET, because + # the response will not be from the broadcast address and thus it + # would not be detected. Rather, I'll have to add the PeerAddress + # directly in the send command, so that the recv command does + # not do any peer address matching. It will then correctly receive + # the responses from any responding device. + my $br_addr = sockaddr_in ($port_command, INADDR_BROADCAST); + my $broadcast = IO::Socket::INET->new ( + PeerPort => $port_command, + Proto => 'udp', + Broadcast => 1 ) + or die "Can't bind broadcast socket: $@\n"; + my $sel = IO::Select->new( $broadcast ); -############################################################################### -## INFRASTRUCTURE WIRELESS SETUP (i.e. wlan through access point / router) -############################################################################### - - -sub wifi_ask_ssid ($) { - my $dev = shift; - my $aps = scan_for_aps ($dev); - print_wireless_networks ($aps); - my @ssids = (sort {lc $a cmp lc $b} keys (%$aps)); - my $newssid; - print "Please enter the number or the SSID of the desired wireless network.\n"; - print "\tEnter '0', 'hidden' or 'h' to connect to a hidden network.\n"; - print "\tEnter 'r' or 'rescan' to rescan for wireless networks.\n"; - do { - print "Desired wireless network: "; - $newssid = input (); - return $newssid if (exists $aps->{$newssid}); - if ($newssid =~ /^[1-9]\d*$/ && ($newssid <= scalar(@ssids))) { - return ($aps,$ssids[$newssid-1]); - } - if ($newssid eq "0" || $newssid eq "h" || $newssid eq "hidden") { - $newssid = ""; - while (length($newssid) < 1) { - print "Please enter the SSID: "; - $newssid = input (); + while (++$loop <= 3 && scalar(%$result) < 5) { + print "."; + $broadcast->send( $request, 0, $br_addr ) + or die "Error at sending: $!\n"; + while ($sel->can_read (1)) { + my $data=""; + $broadcast->recv ($data, 8096); + my $found = SBSU_status_parse ($data); + if ($found) { + $found->{'ip'} = $broadcast->peerhost (); + # Setup the sockets + $result->{$found->{'device-name'}} = $found; } - return ($aps,$newssid); - } - if ($newssid eq "r" || $newssid eq "rescan") { - return wifi_ask_ssid ($dev); } - } while 1; # We'll jump out of the loop via return! -} - -sub wifi_ask_address ($$) { - my $ap = shift; - my $aps = shift; - my $dhcp = ask_choice ("IP-address assignment:", ["DHCP", "Manual"], ["Enable", "Disable"], "Enable"); - my %result = ("dhcp" => $dhcp); - if ($dhcp ne "Enable") { - $result{'ip_addr'} = ask_ip_address ("IP-address of the device:\t"); - $result{'mask'} = ask_ip_address ("Netmask:\t"); - $result{'gateway'} = ask_ip_address ("IP-address of the gateway:\t"); - } else { - $result{'ip_addr'} = "0.0.0.0"; - $result{'mask'} = "0.0.0.0"; - $result{'gateway'} = "0.0.0.0"; } - return %result; -} + foreach (keys %$result) { + # Setup the udp sockets: + my $peer = $result->{$_}->{'ip'}; + $result->{$_}->{'socket-info'} = IO::Socket::INET->new ( + PeerAddr => $peer, + PeerPort => $port_information, + Proto => 'udp' ); + $result->{$_}->{'socket-config'} = IO::Socket::INET->new ( + PeerAddr => $peer, + PeerPort => $port_command, + Proto => 'udp' ); -sub wifi_ask_security ($$) { - my $ap = shift; - my $aps = shift; - my %result = (); - my $sec = 0; - if (defined $aps->{$ap}) { - $sec = $aps->{$ap}->{'secmode'}; - $result{'channel'} = $aps->{$ap}->{'channel'}; - } - $sec = ask_choice ("Security: ", ["None", -1, "WEP", "WPA-PSK", "WPA2-PSK", "WPA/WPA2-PSK"], ['0', '1', '2', '4', '6'], $sec); - $result{'secmode'} = $sec; - - if ($sec == 0) { - # No encryption, nothing to ask the user - } elsif ($sec == 1) { - # WEP - progress "Using WEP security\n"; - $result{'authen'} = ask_choice ("Type of authentication:", ["Open System","Shared Key"], ['1','2'], '1'); - $result{'key'} = ask_wep_key ($ap); - $result{'key_len'} = length ($result{'key'})/2; - } elsif ($sec == 2 || $sec == 4 || $sec == 6 || $sec == 7) { - # WPA1 / WPA2 - progress "Using %s security\n", security2string($sec); - $result{'pskalset'} = ask_choice ("Type of encryption:", ["TKIP", "AES"], ['0','1'], '0'); - $result{'pskkey'} = ask_input ("Please enter the WPA passphrase for network '$ap': ", - \&is_wpa_passphrase, "\tEnter a passprase with 1-63 characters!\n"); - } else { - printf "ERROR: security type %s not supported\n", security2string($sec); - return wifi_ask_security ($ap, $aps); + info_data_write ($result->{$_}, [[undef, "9801", " "]]); + $result->{$_}->{'mac'} = info_data_read ($result->{$_}); } - return %result; -} - -sub wifi_config_create ($) { - my $newconfig = shift; - my $config = [ - ["4000", "IP_ADDR", $newconfig->{'ip_addr'}], # IP-address - ["4001", "GATEWAY", $newconfig->{'gateway'}], - ["4002", "MASK ", $newconfig->{'mask'}], - ["4020", "DHCP_MODE", $newconfig->{'dhcp'}], - ["4021", "", $newconfig->{'dhcp'}], # Unknown, == 4020 - ["4022", "", $newconfig->{'dhcp'}], # Unknown, == 4020 - ["5000", "", ""], # Unknown, always empty - ["5003", "", ""], # Unknown, always empty - ["5101", "", ""], # Unknown, always empty - ["5102", "", ""], # Unknown, always empty - ["5104", "", ""], # Unknown, always empty - ["5103", "", ""], # Unknown, always empty - ["7000", "SSID", $newconfig->{'SSID'}], - ["7001", "DOMAIN", ""], - ["7002", "CHANNEL", $newconfig->{'channel'}], - ["7003", "SECMODE", $newconfig->{'secmode'}], - ["7004", "KEY_LEN", $newconfig->{'key_len'}], - ["7005", "DEFAULTKEY","0"], - ["7006", "KEY0", $newconfig->{'key'}], - ["7007", "KEY1", ""], - ["7008", "KEY2", ""], - ["7009", "KEY3", ""], - ["7012", "AUTHEN", $newconfig->{'authen'}], - ["7013", "MODE", "0"], - ["7018", "PSKALSET", $newconfig->{'pskalset'}], - ["7019", "PSKKEY", $newconfig->{'pskkey'}], - ["7024", "STAMODE", "0"], - ["7025", "APCHANNEL", "5"], - ["7026", "CHMODE", "1"], - ["7030", "WLMODE", "0"], - ]; - return config_create ($config); + return $result; } +sub device_select ($) { + my $devs = shift; -############################################################################### -## AD-HOC WIRELESS SETUP (i.e. direct connection with print server and PC) -############################################################################### + my @d = (); + my @dn = (); + my $format = "%-18s%-15s%-30s"; + foreach my $dd (keys %$devs) { + my $devinfo = $devs->{$dd}; + push @d, sprintf ($format, $devinfo->{'device-name'}, $devinfo->{'ip'}, $devinfo->{'printer-name'}); + push @dn, $dd; + } + my $text = "The following devices were found:\n\n\t " . + sprintf ($format, "Device", "IP", "Detected printer") . "\n" . + "\t ------------------------------------------------------------------------"; + if (scalar (@d) == 1) { + print $text; + print @d[0]; + } else { + return ask_choice ($text, -sub adhoc_send_unknown_command ($) { - my $dev = shift; - bulk_data_write ($dev, "9971:\n", 6); - my $val = ""; - bulk_data_read ($dev, $val, 1); - debug "\tResponse to 9971 Ad-hoc setting command (unknown purpose): %s\n", $val; - return $val; + \@d, + \@dn, + @dn[0] + ); + } } -sub adhoc_ask_ssid ($) { - my $dev = shift; - my $ssid = ""; - print "\n"; - do { - print "SSID of the ad-hoc wireless connection:"; - $ssid = input (); - if (length ($ssid) > 0) { - # scan for wireless networks to check for name clashes - my $aps = scan_for_aps ($dev); - if (defined ($aps->{$ssid})) { - print "\tERROR: wireless network '$ssid' already exists, please choose a different name.\n\n"; - } else { - return $ssid; - } - } - } while 1; # We'll jump out of the loop via return! -} -sub adhoc_ask_channel ($$) { - my $dev = shift; - my $ap = shift; - my $channel; - do { - printf "Wireless channel for network '%s' [auto or 0-13]: ", $ap; - my $c = input (); - if ($c eq "auto") { - $channel = "6"; # FIXME - } elsif ($c =~ m/^([0-9]|1[0-3])$/ ) { - $channel = $c; - } - } while (!defined ($channel)); - debug "\tNew channel: %s\n", $channel; - return $channel; -} -sub adhoc_ask_security ($) { - my $ssid = shift; - my %result = (); - my $sec = ask_choice ("Security: ", - ["None", -1, "WEP", "WPA-PSK", "WPA2-PSK", "WPA/WPA2-PSK"], - ['0', '1', '2', '4', '6'], - 0); - $result{'secmode'} = $sec; - - if ($sec == 0) { - # No encryption, nothing to ask the user - } elsif ($sec == 1) { - # WEP - progress "Using WEP security\n"; - $result{'key'} = ask_wep_key ($ssid); - $result{'key_len'} = length ($result{'key'})/2; - } elsif ($sec == 2 || $sec == 4 || $sec == 6 || $sec == 7) { - # WPA1 / WPA2 - progress "Using %s security\n", security2string($sec); - $result{'pskalset'} = ask_choice ("Type of encryption:", ["TKIP", "AES"], ['0','1'], '0'); - $result{'pskkey'} = ask_input ("Please enter the WPA passphrase for network '$ssid': ", - \&is_wpa_passphrase, "\tEnter a passprase with 1-63 characters!\n"); - } else { - printf "ERROR: security type %s not supported\n", security2string($sec); - return adhoc_ask_security ($ssid); - } - return %result; -} -sub adhoc_config_create ($) { - my $newconfig = shift; - my $config = [ - ["7024", "STAMODE", "1"], - ["7025", "APCHANNEL", $newconfig->{'channel'}], - ["7026", "CHMODE", "1"], # FIXME: Shall we change this? - ["7030", "WLMODE", "1"], # FIXME: Shall we change this? - ["7100", "APSSID", $newconfig->{'SSID'}], - ["7103", "APSECMODE", $newconfig->{'secmode'}], - ["7104", "APKEY_LEN", $newconfig->{'key_len'}], - ["7105", "APDEFAULTKE","0"], - ["7106", "APKEY0", $newconfig->{'key'}], - ["7107", "APKEY1", ""], - ["7108", "APKEY2", ""], - ["7109", "APKEY3", ""], - ["7112", "APAUTHEN", $newconfig->{'authen'}], - ["7118", "APPSKALSET", $newconfig->{'pskalset'}], - ["7119", "APPSKKEY", $newconfig->{'pskkey'}] - ]; - return config_create ($config); -} @@ -783,91 +448,19 @@ sub adhoc_config_create ($) { ############################################################################### -sub ask_operation () { - return ask_choice ( - "What do you want to do?", - ["Setup a wireless connection through a wifi router or access point ('infrastructure')", - "Setup a direct wireless connection with the printer ('ad-hoc')", - -1, - "Change the name of the device", - -1, - "Save the device configuration to a file", - "Restore the device configuration from a file", - -1, - "Reload the configuration", - "Exit" - ], - ["wifi_infrastructure", - "wifi_adhoc", - "change_hostname", - "config_save", - "config_restore", - "reload", - "exit" - ], - "exit"); -} - sub main () { - device_detect (); -# my $reconfigured = 0; -# my $dev = device_detect () or exit; -# device_open ($dev); -# my $cfg = device_config_request ($dev); -# my @config = config_parse ($cfg); -# print_current_configuration (\@config, "Current configuration of the device:\n"); -# # Ask what to do (set wifi AP, ad-hoc, save, restore) -# my $operation = ask_operation (); -# debug ("\tSelected operation: %s\n", $operation); -# if ($operation eq "wifi_infrastructure") { -# # Infrastructure, scan for APs -# my ($aps,$newap) = wifi_ask_ssid ($dev); -# my %newconfig = ('SSID' => $newap); -# debug ("\tSelected wireless network: %s\n", $newap); -# my %security = wifi_ask_security ($newap, $aps); -# my %ip = wifi_ask_address ($newap, $aps); -# %newconfig = (%newconfig, %security, %ip); -# my $newcfg = wifi_config_create (\%newconfig); -# device_config_send ($dev, $newcfg); -# $reconfigured = 1; -# } elsif ($operation eq "wifi_adhoc") { -# # Ad-hoc connection to print server -# my $adhocssid = adhoc_ask_ssid ($dev); -# adhoc_send_unknown_command ($dev); -# my $channel = adhoc_ask_channel ($dev, $adhocssid); -# my %newconfig = ('SSID' => $adhocssid, -# 'channel' => $channel, -# adhoc_ask_security ($adhocssid) -# ); -# my $newcfg = adhoc_config_create (\%newconfig); -# device_config_send ($dev, $newcfg); -# $reconfigured = 1; -# } elsif ($operation eq "change_hostname") { -# set_hostname ($dev); -# $reconfigured = 1; -# } elsif ($operation eq "config_save") { -# my $filename = ask_input ("Filename to save to: ", \&is_filename, ""); -# device_config_save ($filename, $cfg); -# } elsif ($operation eq "config_restore") { -# my $filename = ask_input ("Filename to load from: ", \&is_filename, ""); -# device_config_restore ($dev, $filename); -# } elsif ($operation eq "reload") { -# # do nothing, we'll call main below... -# } elsif ($operation eq "exit") { -# device_close ($dev); -# exit; -# } else { -# printf "ERROR: unknown operation %s\n", $operation; -# } -# device_close ($dev); -# # if the configuration was changed, print the new config after the device was reset -# $dev = device_detect () or exit; -# device_open ($dev); -# @config = config_parse (device_config_request ($dev)); -# print_current_configuration (\@config, "New configuration of the device:\n"); -# -# # Loop in main if "reload" is selected... -# main () if ($operation eq "reload"); + my $devs = device_detect (); + if (scalar($devs) == 0) { + print "No supported devices detected on the network. Supported devices are:\n"; + foreach (@supported_devices) { + print "\t-)$_\n"; + } + print "\n"; + exit 0; + } + my $d = device_select ($devs); +# print Dumper (\@d); + # TODO }