diff --git a/hp2101nw_connect.pl b/hp2101nw_connect.pl new file mode 100755 index 0000000000000000000000000000000000000000..d05ab490674390767aae3c2eba02ec649da060ca --- /dev/null +++ b/hp2101nw_connect.pl @@ -0,0 +1,880 @@ +#!/usr/bin/perl +## hp2101nw_connect.pl - version 0.01 +## +## Linux connection utility for the HP 2101nw wireless G USB print server. +## +## (C) 2012 Reinhold Kainhofer <reinhold@kainhofer.com> +## License: GPL v2 or later + +## This script (hp2101nw_connect.pl) provides a relatively easy way to identify and +## connect to the HP 2101nw wireless USB print server on linux. +## The device is not a real print server, but rather a USB port forwarder +## over TCP/UDP. On Windows it creates a virtual USB port, so for Linux +## support, we'll need a proper kernel module doing the USB port forwarding... +## +## This script "only" detects the device on the network, retrieves information and +## optionally lock it. Once a kernel module is ready, this is the user-space +## part of the driver. +## +## For the device protocol see: +## http://wiki.kainhofer.com/hardware/hp2101nw_wlan_printserver + +## Supported devices: +## -) HP 2101nw wireless G USB print server (USB-id 03f0:cd02) + + +use IO::Socket; +use IO::Select; +# use Socket qw(:all); +use Data::Dumper; +use strict; +# use warnings; + +our $debug=1; + +our $VERSION=0.01; +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"; +print "License: GPL v2 or later\n\n"; + + +# The PC always identifies itself as XXXXXXXX. +our $thisboxname = "XXXXXXXX"; +our $port_information = 34444; +our $port_command = 34447; +our $port_usbnet = 34448; + +our $SBSU_STATUS = 1; +our $SBSU_UNKNOWN = 7; + +$| = 1; + + +$Data::Dumper::Indent = 1; + +# USB vendor / product ids and descriptions of all supported devices +my @supported_devices=( + [0x03f0, 0xcd02, "HP 2101nw wireless G USB print server"] +); + + + +############################################################################### +## HELPER FUNCTIONS +############################################################################### + + +sub progress { + printf (@_); +} +sub debug { + if ($debug) { + printf (@_); + } +} +sub trim ($) { + my $string = shift; + $string =~ s/^\s+//; + $string =~ s/\s+$//; + return $string; +} +sub input () { + chomp (my $input = <STDIN>); + $input = trim ($input); + return $input; +} +sub sleep_progress ($) { + my $dur = shift; + do { + progress "."; + sleep (1); + --$dur; + } while ($dur > 0); + progress "\n"; +} + + + +# Give the user a number of choices to select from. +# $text ... text to print before the options +# $options ... array ref containing human-readable option values (-1 for separator) +# $values ... array ref with option values (-1 in $options are ignored!) +# $default ... default value if empty input is given +sub ask_choice ($$$$) { + my $text = shift; + my $options = shift; + my $values = shift; + my $default = shift; + my $defindex = 0; + print "$text\n"; + my $i=1; + foreach (@$options) { + if ($_ == -1) { + print "\t---\n"; + } else { + print "\t$i) $_\n"; + if ($values->[$i-1] eq $default) { + $defindex = $i; + } + ++$i; + } + } + my $retval; + do { + print "Your choice (default: $defindex): "; + my $op = input (); + if ($op eq "") { + $retval = $default; + } elsif (($op =~ m/^[1-9][0-9]*$/) && ($op <= scalar (@$values))) { + $retval = $values->[$op-1]; + } else { + printf "\tInvalid input. Please enter a number from 1 to %d, or simply press Return to use the default.\n", scalar (@$values); + } + } while (!defined $retval); + return $retval; +} + +# Ask the user for some text input, which will be validated (if invalid input +# is given, the user is notified and asked again. +# $text ... text to ask the user +# $validator ... callback function to validate the input +# $message ... error message printed if validation fails. +sub ask_input ($$$) { + my $text = shift; + my $validator = shift; + my $message = shift; + my $retval; + my $valid = 0; + do { + print $text; + $retval = input (); + $valid = &$validator ($retval); + if (!$valid) { + printf $message, $retval; + } + } while (!$valid); + return $retval; +} + +######################## +# validation functions + +sub is_ip_address ($) { + my $ip = shift; + return ($ip =~ m/^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/); +} + +sub ask_ip_address ($) { + return ask_input (shift, \&is_ip_address, "\tInvalid input %s. Please enter a string of the form xxx.xxx.xxx.xxx, where each xxx is a number from 0 to 255.\n"); +} + +sub is_filename ($) { + my $fn = shift; + return (length($fn)>0); +} + +sub is_hostname ($) { + return (shift =~ m/^[-A-Za-z0-9]{1,63}$/ ) +} + + + +############################################################################### +## 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 SBSU_create_buffer ($) { + my $cmd = shift; + return sprintf ("SBSU%s", pack("v", $cmd)); +} + +# 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 ($) { + +} + +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 ); + + 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; + } + } + print "\nResult: @result\n"; + return @result; +} + +sub device_info ($) { + my $ip = shift (); + +} + +sub create_status_request () { +} + +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 ($) { + my $dev = shift; + $dev->release_interface(0); + $dev->reset; +} + + + +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; +} + +# Read USB bulk data into the second argument (output argument!), return +# size of data +sub bulk_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 +############################################################################### + + +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); + } + 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"; + } + 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); +} + +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) { + $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 device_config_restore ($$) { + my $dev = shift; + my $filename = shift; + my $status = open FILE, "<$filename"; + if (!$status) { + printf "ERROR: %s\n", $!; + return; + } + 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); +} + + + + + + +############################################################################### +## 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; +} + + +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"; +} + + + +############################################################################### +## 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 (); + } + 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; +} + +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); + } + 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); +} + + + +############################################################################### +## AD-HOC WIRELESS SETUP (i.e. direct connection with print server and PC) +############################################################################### + + +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; +} + +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); +} + + + +############################################################################### +## MAIN OPERATIONS: ASK FOR OPERATION AND HANDLE IT +############################################################################### + + +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"); +} + + + + +############################################################################### +## MAIN FUNCTION +############################################################################### + +main ();