Skip to content
Snippets Groups Projects
Commit 82d4e258 authored by Reinhold Kainhofer's avatar Reinhold Kainhofer
Browse files

Implement config and wifi networks scanning, print them and ask for AP

parent 1ab38b4d
No related branches found
No related tags found
No related merge requests found
......@@ -7,18 +7,17 @@ use strict;
use warnings;
my $debug=1;
# my $debug=0;
our $VERSION=0.01;
print "hp2101nw_setup.pl - version $VERSION\n";
print "Linux configuration utility for the HP 2101nw wireless G USB print server.\n\n";
print "(C) 2011 Reinhold Kainhofer <reinhold\@kainhofer.com>\n";
print "License: GPL v2 or later\n\n";
=head1 NAME
hp2101nw_setup.pl - Configure the HP 2101nw wireless G USB print server
=head1 VERSION
Version 0.01
=cut
our $VERSION=0.01;
our $thisboxname = "XXXXXXXX";
$| = 1;
=head1 SYNOPSIS
......@@ -34,39 +33,51 @@ http://wiki.kainhofer.com/hardware/hp2101nw_wlan_printserver
=cut
print "hp2101nw_setup.pl - version $VERSION\n";
print "Linux configuration utility for the HP 2101nw wireless G USB print server.\n\n";
print "(C) 2011 Reinhold Kainhofer <reinhold\@kainhofer.com>\n";
print "License: GPL v2 or later\n\n";
$Data::Dumper::Indent = 1; ## no critic(ProhibitPackageVars)
# data structure: VendorID, ProductID, BULK_IN_EP, BULK_OUT_EP
my @supported_devices=(
[0x03f0, 0xcd02]
);
my $var_names = {};
sub progress {
# my $str = shift;
printf (@_);
}
sub debug {
if ($debug) {
printf (@_);
}
}
sub trim($) {
my $string = shift;
$string =~ s/^\s+//;
$string =~ s/\s+$//;
return $string;
}
sub device_detect () {
my $usb = Device::USB->new();
my $dev;
print "Detected devices:\n";
progress "Detected devices:\n";
foreach (@supported_devices) {
$dev = $usb->find_device( @$_ );
if ($dev) {
printf "\t%s / ID %04x:%04x (%s: %s)\n", $dev->filename(),
progress ("\t%s / ID %04x:%04x (%s: %s)\n", $dev->filename(),
$dev->idVendor(), $dev->idProduct(),
$dev->manufacturer(), $dev->product();
$dev->manufacturer(), $dev->product());
}
}
if ($dev) {
printf "\nUsing device: %04x:%04x (%s: %s)\n\n",
$dev->idVendor(), $dev->idProduct(),
$dev->manufacturer(), $dev->product();
progress "\n";
debug ("Using device: %04x:%04x (%s: %s)\n\n",
$dev->idVendor(), $dev->idProduct(),
$dev->manufacturer(), $dev->product() );
} else {
print "\tNONE\n\n";
progress "\tNONE\n\n";
print "ERROR: No supported device was found...\n\n";
print "Please connect your HP wireless USB print server to \n";
print "the computer with the black USB cable (micro USB plug) \n";
......@@ -101,26 +112,213 @@ sub device_open ($) {
}
sub request_device_config ($) {
sub write_bulk_data ($$$) {
my $dev = shift;
my $request = "@\0\x06\0XXXXXXXX9100:\n";
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);
if ($debug) { print "Request: ", $request, "\n"; }
my $res = $dev->bulk_write (1, $request, 18, 1000);
my $res = $dev->bulk_write (1, $request, 18, 500);
if ($res<0) {
printf "ERROR write bulk data (%d): %s\n", $res, $!;
}
$res = $dev->bulk_read (2, my $result="", 25600, 1000);
return $res;
}
# Read bulk data, maybe in loops until there is nothing left to read?
sub read_bulk_data ($$$) {
my $dev = shift;
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, $!;
}
if ($debug) { printf "read %d bytes: \n%s\n\n", $res, $result; }
return $result;
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 security2string {
my $sec = shift;
if ($sec == 0) {
return "None";
} elsif ($sec == 1) {
return "WEP";
} elsif ($sec == 2) {
return "WPA-PSK";
} elsif ($sec == 4) {
return "WPA2-PSK"; # WPA2-PSK TKIP
} elsif ($sec == 6) {
return "WPA/WPA2-PSK"; # WPA/WPA2 and WPA2-PSK CCMP
} elsif ($sec == 7) {
return "WPA-EAP";
} elsif ($sec == 8) {
return "WPA2-EAP";
} else {
return sprintf ("Unknown (%d)", $sec);
}
}
sub val {
my $config = shift;
my $var = shift;
foreach my $e (@$config) {
if ($e->[0] eq $var) {
return $e->[2];
}
}
return undef;
}
sub print_current_configuration ($) {
my $config = shift;
print "Current configuration of the device:\n";
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;
}
printf "\tSSID: %s\n", val($config,'7000');
printf "\tSecurity: %s\n", security2string (val($config,'7003'));
printf "\tChannel: %s\n", val($config,'7002');
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) {
printf "\tLink state: %s\n", val($config,'7014');
} else {
# Not connected
printf "\tWireless not connected\n";
}
# TODO: Print ad-hoc network setting if configured/enabled
print "\n\n";
}
sub request_device_config ($) {
my $dev = shift;
my $cfg = "";
progress "Reading current configuration...\n";
my $res = write_bulk_data ($dev, "9100:\n", 6);
$res = read_bulk_data ($dev, $cfg, 25600);
return $cfg;
}
sub parse_device_config ($) {
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]);
# print "key: ", $key, ", name: ", $name, ", value: ", $value, "\n";
}
return @config;
}
# Convert a list of the form [ ["OPTIONID", "OPTIONNAME", "VALUE], ...]
# into a string to be sent to the device
sub create_config ($) {
my $cfg = shift;
my $result = "";
foreach my $o (@$cfg) {
$result .= sprintf ("%s %s:%s\n", $o->[0], $o->[1], $o->[2]);
}
return $result;
}
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]
};
# "SSID: ", $ssid, "settings: ", @settings, "\n";
# print "entry: |", $_, "|\n";
}
debug Dumper ($networks);
return $networks;
}
sub scan_for_aps ($) {
my $dev = shift;
progress "Scanning for access points: ";
my $loop = 0;
my $found;
my $survey;
while (!defined($found) && $loop <= 4) {
++$loop;
debug ("loop=", $loop, "\n");
my $res = write_bulk_data ($dev, "9107:\n", 6);
$res = read_bulk_data ($dev, my $d="", 0);
foreach (1, 2, 3, 4, 5) {
sleep(1);
progress ".";
}
my $cfg = "";
$res = write_bulk_data ($dev, "9100:\n", 6);
$res = read_bulk_data ($dev, $cfg, 25600);
my @config = parse_device_config ($cfg);
$survey = val(\@config, '7021');
$found = (defined ($survey) && length ($survey) > 0);
}
progress "\n";
if ($found) {
# progress "Found wireless networks: \n", $survey;
} else {
print "ERROR: No wireless networks detected.\n";
}
return parse_survey_data ($survey);
}
sub print_wireless_networks {
my $aps = shift;
print "Detected wireless networks:\n";
# print Dumper ($aps);
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";
}
......@@ -131,12 +329,53 @@ sub device_close ($) {
$dev->reset;
}
sub ask_change {
my $exit = "";
until ($exit =~ /^[yn]/i ) {
print "Do you want to change these settings? (y,n) ";
chomp($exit = <STDIN>);
$exit = trim($exit);
}
return ($exit =~ /^y/i);
}
sub ask_ap {
my $aps = shift;
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 "Enter '0', 'hidden' or 'h' to connect to a hidden network.\n";
do {
print "Desired wireless network: ";
chomp($newssid = <STDIN>);
$newssid = trim ($newssid);
return $newssid if (exists $aps->{$newssid});
if ($newssid =~ /^[1-9]\d*$/ && ($newssid <= scalar(@ssids))) {
return $ssids[$newssid-1];
}
if ($newssid eq "0" || $newssid eq "h" || $newssid eq "hidden") {
$newssid = "";
while (length($newssid) < 1) {
print "Please enter the SSID: ";
chomp ($newssid = <STDIN>);
}
return $newssid;
}
} while 1; # We'll jump out of the loop via return!
}
my $dev = device_detect ();
if ($dev) {
device_open ($dev);
my $cfg = request_device_config ($dev);
my $cfg_array = parse_device_config ($cfg);
my @config = parse_device_config ($cfg);
print_current_configuration (\@config);
# TODO: Ask whether configuration shall be changed
exit unless (ask_change ());
my $aps = scan_for_aps ($dev);
print_wireless_networks ($aps);
my $newap = ask_ap ($aps);
debug ("\tNew wireless network: |%s|\n", $newap);
device_close ($dev);
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment