diff --git a/appliance_setup/appliance_setup.py b/appliance_setup/appliance_setup.py
index 360dfa05cbfe3b0daa0bc01811d42bd7b0547893..8915d9798e3f88576a1e6e29ce89748025bad3c8 100755
--- a/appliance_setup/appliance_setup.py
+++ b/appliance_setup/appliance_setup.py
@@ -73,130 +73,20 @@ def ask_device (ui):
 
 
 
-"""
-
-###############################################################################
-##  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 scan_for_aps ($) {
-  my $dev = shift;
-  progress "Scanning for access points: ";
-  my $loop = 0;
-  my $found = 0;
-  my $survey;
-  while (!$found && $loop <= 4) {
-    ++$loop;
-    debug ("loop=", $loop, "\n");
-    my $res = bulk_data_write ($dev, "9107:\n", 6);
-    $res = bulk_data_read ($dev, my $d="", 0);
-    sleep_progress (6);
-    my $cfg = "";
-    $res = bulk_data_write ($dev, "9100:\n", 6);
-    $res = bulk_data_read ($dev, $cfg, 25600);
-    my @config = config_parse ($cfg);
-    $survey = val(\@config, '7021');
-    $found = (defined ($survey) && length ($survey) > 0);
-  }
-  progress "\n";
-  if ($found) {
-    debug "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";
-  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 {
-    $newssid = input ("Desired wireless network: ");
-    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) {
-        $newssid = input ("Please enter the SSID: ");
-      }
-      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!
-}
+def wifi_ask_ssid (ui, dev):
+  while True:
+    aps = dev.scan_for_aps ()
+    res = ui.ask_wireless_ap (aps)
+    print "SSID is {}".format(res)
+    if res:
+      return (res, aps)
 
-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;
@@ -268,40 +158,28 @@ sub wifi_config_create ($) {
   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 {
-    $ssid = input ("SSID of the ad-hoc wireless connection:");
-    if (length ($ssid) > 0) {
+def adhoc_ask_ssid (ui, dev):
+  ssid = ""
+  ui.progress ("")
+  while True:
+    ssid = ui.input ("SSID of the ad-hoc wireless connection:")
+    if (len(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!
-}
+      aps = dev.scan_for_aps ()
+      if (aps.get(ssid)):
+        ui.error ("wireless network '%s' already exists, please choose a different name.\n" % ssid)
+      else:
+        return ssid
 
+"""
 def adhoc_ask_channel (ap):
   channel = False
   while (!channel):
@@ -375,8 +253,8 @@ def ask_operation (ui, dev):
 def main ():
   reconfigured = False
   operation = ""
-  UI = ConsoleInterface (debug=True)
-  
+  UI = ConsoleInterface (debug=False)
+
   dev = ask_device (UI)
   if (not dev or not dev.device_open ()):
     return
@@ -391,21 +269,23 @@ def main ():
   UI.debug ("\tSelected operation: %s\n" % operation)
   if (operation == "wifi_infrastructure"):
     ## Infrastructure, scan for APs
-    # TODO
-    #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);
+    (newap, aps) = wifi_ask_ssid (UI, dev)
+    newconfig = {'SSID': newap)
+    UI.debug ("\tSelected wireless network: %s" % newap)
+    security = UI.wifi_ask_security ()#TODO: $newap, $aps);
+    newconfig.update (security)
+    if (dev.capabilities['ip-address']):
+      ip = UI.ask_IP_setting ()
+      newconfig.update (ip)
+    # TODO:
     #my $newcfg = wifi_config_create (\%newconfig);
     #device_config_send ($dev, $newcfg);
     reconfigured = True
   elif (operation == "wifi_adhoc"):
     ## Ad-hoc connection to print server
     # TODO
-    #my $adhocssid = adhoc_ask_ssid ($dev);
-    #adhoc_send_unknown_command ($dev);
+    adhocssid = adhoc_ask_ssid (UI, dev)
+    dev.command_send ("9971:\n")
     #my $channel = adhoc_ask_channel ($dev, $adhocssid);
     #my %newconfig = ('SSID' => $adhocssid,
                      #'channel' => $channel,
diff --git a/appliance_setup/configuration.py b/appliance_setup/configuration.py
index b118a58ae0dd101192a249d9fd2d35ab6804fea6..6505a995f13e3871d693b3b16d34deebde22dcda 100644
--- a/appliance_setup/configuration.py
+++ b/appliance_setup/configuration.py
@@ -34,58 +34,57 @@ class Config:
     self.cfgdata = cfg
 
   def print_configuration (self, text):
-    #print self.cfgstring
-    ##print self.cfgdata
-    #print self.val('0012')
-    res = text + "\tDevice name:   %s\n" % self.val('0001')
-    if (self.val('0012') != "Enable"):
-      res += "\tTCP/IP not yet configured and/or enabled.\n\n"
-      return res
+    res = text + "\tDevice name:\t%s\n" % self.val('0001')
     adhoc = (self.val('7024') == '1')
     if adhoc:
       # ad-hoc network:
       sec = self.val('7103');
-      res += "\tWireless mode: Ad-hoc network\n"
-      res += "\tSSID:          %s\n" % self.val('7100')
-      res += "\tChannel:       %s\n" % self.val('7102')
-      res += "\tSecurity:      %s\n" % security2string (sec)
+      res += "\tWireless mode:\tAd-hoc network\n"
+      res += "\tSSID:\t\t%s\n" % self.val('7100')
+      res += "\tChannel:\t%s\n" % self.val('7102')
+      res += "\tSecurity:\t%s\n" % security2string (sec)
       if (sec == 0):
         # None => nothing to display
         pass
       elif (sec == 1):
         # WEP => Print passphrase
-        res += "\tWEP Key:       %s\n" % self.val('7106')
+        res += "\tWEP Key:\t%s\n" % self.val('7106')
       else:
         # WPA 1/2 or mixed
-        res += "\tEncryption:    %s\n" % encryption2string(self.val('7118'))
-        res += "\tPassphrase:    %s\n" % self.val('7119')
+        res += "\tEncryption:\t%s\n" % encryption2string(self.val('7118'))
+        res += "\tPassphrase:\t%s\n" % self.val('7119')
     else:
       # infrastructure network
       sec = self.val('7003');
-      res += "\tSSID:          %s\n" % self.val('7000')
-      res += "\tChannel:       %s\n" % self.val('7002')
-      res += "\tSecurity:      %s\n" % security2string (sec)
+      res += "\tSSID:\t\t%s\n" % self.val('7000')
+      res += "\tChannel:\t%s\n" % self.val('7002')
+      res += "\tSecurity:\t%s\n" % security2string (sec)
       if (sec == 0):
         # None => nothing to display
         pass
       elif (sec == 1):
         # WEP => Print passphrase
-        res += "\tAuthentication:  %s\n" % authentication2string(self.val('7012'))
-        res += "\tWEP Key:       %s\n" % self.val('7006')
+        res += "\tAuthentication:\t%s\n" % authentication2string(self.val('7012'))
+        res += "\tWEP Key:\t%s\n" % self.val('7006')
       else:
         # WPA 1/2 or mixed
-        res += "\tEncryption:    %s\n" % encryption2string(self.val('7018'))
-        res += "\tPassphrase:    %s\n" % self.val('7019')
+        res += "\tEncryption:\t%s\n" % encryption2string(self.val('7018'))
+        res += "\tPassphrase:\t%s\n" % self.val('7019')
   
-    dhcp = (self.val('4020') == "Enable")
-    res += "\tIPv4 method:   %s\n" % ("DHCP" if dhcp else "manual")
-    associated = (self.val('7014').find ("STATE:Associated") >= 0)
-    if (associated or not dhcp):
-      res += "\tIP address:    %s\n" % self.val('4000')
-      res += "\tGateway:       %s\n" % self.val('4001')
-      res += "\tNetmask:       %s\n" % self.val('4002')
+    associated = (self.val('7014').find ("STATE:Associated") >= 0) or \
+                 (self.val('7014').find ("STATE:Connected") >= 0)
+    if (self.get ('4000')):
+      dhcp = (self.val('4020') == "Enable")
+      res += "\tIPv4 method:\t%s\n" % ("DHCP" if dhcp else "manual")
+      if (associated or not dhcp):
+        res += "\tIP address:\t%s\n" % self.val('4000')
+        res += "\tGateway:\t%s\n" % self.val('4001')
+        res += "\tNetmask:\t%s\n" % self.val('4002')
+    else:
+      res += "\tDevice does not receive an IP address\n"
+
     if associated:
-      res += "\tLink state:    %s\n" % self.val('7014')
+      res += "\tLink state:\t%s\n" % self.val('7014').replace ("\x0b", "\n\t\t\t").replace (";", "\n\t\t\t")
     else:
       # Not connected
       res += "\tWireless not connected\n"
@@ -141,175 +140,14 @@ class Config:
 
 
 
-
-
-###############################################################################
-##  DEVICE CONFIGURATION HANDLING
-###############################################################################
-
 """
 
 
-
-
-
-
-###############################################################################
-##  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 scan_for_aps ($) {
-  my $dev = shift;
-  progress "Scanning for access points: ";
-  my $loop = 0;
-  my $found = 0;
-  my $survey;
-  while (!$found && $loop <= 4) {
-    ++$loop;
-    debug ("loop=", $loop, "\n");
-    my $res = bulk_data_write ($dev, "9107:\n", 6);
-    $res = bulk_data_read ($dev, my $d="", 0);
-    sleep_progress (6);
-    my $cfg = "";
-    $res = bulk_data_write ($dev, "9100:\n", 6);
-    $res = bulk_data_read ($dev, $cfg, 25600);
-    my @config = config_parse ($cfg);
-    $survey = val(\@config, '7021');
-    $found = (defined ($survey) && length ($survey) > 0);
-  }
-  progress "\n";
-  if ($found) {
-    debug "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";
-  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 {
-    $newssid = input ("Desired wireless network: ");
-    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) {
-        $newssid = input ("Please enter the SSID: ");
-      }
-      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 = [
@@ -353,45 +191,6 @@ sub wifi_config_create ($) {
 ##  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 {
-    $ssid = input ("SSID of the ad-hoc wireless connection:");
-    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!
-}
-
-def adhoc_ask_channel (ap):
-  channel = False
-  while (!channel):
-    c = input ("Wireless channel for network '%s' [auto or 0-13]: " % ap);
-    if (c == "auto"):
-      channel = "6"   # FIXME
-    elif (re.match ('^([0-9]|1[0-3])$', c)):
-      channel = c
-  debug ("\tNew channel: %s\n" % channel)
-  return channel
-
 sub adhoc_config_create ($) {
   my $newconfig = shift;
   my $config = [
diff --git a/appliance_setup/device_types.py b/appliance_setup/device_types.py
index 162cbf911411eb6bc268636904e3dbd9f110c0fa..91051bdcf9e3e7cfe6d5fc1586a78a0b1293b1ec 100755
--- a/appliance_setup/device_types.py
+++ b/appliance_setup/device_types.py
@@ -27,7 +27,7 @@ class Device:
   capabilities = {}
   def __init__ (self, ui):
     self.ui = ui
-    self.capabilities = {'wifi': False, 'ad-hoc': False}
+    self.capabilities = {'wifi': False, 'ad-hoc': False, 'ip-address': False}
 
   def device_string (self):
     pass
@@ -39,32 +39,51 @@ class Device:
     pass
   def device_close (self):
     pass
-  def command_send (self, cmd):
-    cfg = "%s:\n" % cmd
-    res = self.bulk_data_write (cfg, len(cfg))
-    return self.bulk_data_read (25600)
+  def command_send (self, cfg):
+    res = self.data_write (cfg, len(cfg))
+    return self.data_read (25600)
 
   def config_retrieve (self):
     self.ui.debug ("Reading current configuration...");
-    return self.command_send ("9100")
+    return self.command_send ("9100:\n")
 
   def config_send (self, config):
     self.ui.progress ("Sending new configuation to the device. Please wait")
     cfgstring = config.to_string ()
     self.ui.debug ("\tNew device config: %s\n" % cfgstring)
-    self.bulk_data_write (cfgstring, len(cfgstring))
+    self.data_write (cfgstring, len(cfgstring))
     self.ui.sleep_progress (10)
     # Now reset the device:
     return self.device_reset ()
 
-  def bulk_data_write (self, data, length, timeout=500):
+  def data_write (self, data, length, timeout=500):
     pass
-  def bulk_data_read (self, length, timeout=500):
+  def data_read (self, length, timeout=500):
     pass
   def device_reset (self):
     pass
   def scan_for_aps (self):
-    pass
+    self.ui.progress ("Scanning for access points", False)
+    loop = 0
+    found = False
+    survey = ''
+    while (not found and loop <= 4):
+      loop += 1
+      self.ui.debug ("loop=%d\n" % loop)
+      # trigger a WLAN scan
+      self.command_send ("9107:\n")
+      self.ui.sleep_progress (6)
+      cfg = self.config_retrieve ()
+      config = Config (self.ui, cfgstring=cfg)
+      survey = config.val('7021')
+      found = (survey and len(survey) > 0)
+    self.ui.progress ("")
+    if found:
+      self.ui.debug ("Found wireless networks: \n%s" % survey)
+    else:
+      self.ui.error ("No wireless networks detected.")
+    return parse_survey_data (survey)
+
   def print_supported_devices (self):
     pass
   def error (self, msg):
@@ -111,6 +130,7 @@ class USBDevice (Device):
     Device.__init__ (self, ui)
     self.capabilities['wifi'] = True
     self.capabilities['ad-hoc'] = True
+    self.capabilities['ip-address'] = True
     self.dev = dev
     self.desc = desc
     self.bus = bus
@@ -149,8 +169,8 @@ class USBDevice (Device):
 
   def device_reset (self):
     self.ui.progress ("Resetting the device, please wait")
-    res = self.command_send ("9002")
-    self.ui.debug ("\tSent 9002 reset command: %d" % res)
+    res = self.command_send ("9002:\n")
+    self.ui.debug ("\tSent 9002 reset command: %s (len: %s)" % (res, len(res)))
     # Poll the device until it doesn't respond. Then sleep for ~15 seconds
     try:
       i=0
@@ -167,7 +187,7 @@ class USBDevice (Device):
     self.device_close ()
     self.ui.wait_enter ("Device was reset. Please press Return.")
 
-  def bulk_data_write (self, data, length, timeout=500):
+  def data_write (self, data, length, timeout=500):
     # Add the header (12 bytes): '@\0', packet length, boxname (="XXXXXXXX")
     request = "@\0" + struct.pack("<H8s", length, self.thisboxname) + data
     self.ui.debug ("Request: " + request)
@@ -179,7 +199,7 @@ class USBDevice (Device):
     return res
 
   # Read and return USB bulk data
-  def bulk_data_read (self, length, timeout=500):
+  def data_read (self, length, timeout=500):
     # TODO: Get rid of the length argument, simply read all that is sent
     try:
       res = self.handle.bulkRead (2, length+13, timeout);
@@ -225,17 +245,20 @@ import re
 class Ether8888Packet:
   ethHeaderFmt = "!6s6sH"
   headerFmt = "<2s2s2sHH"
-  localAddr="\0\0\0\0\0\0"
-  remoteAddr="\xff\xff\xff\xff\xff\xff"
+  srcAddr="\0\0\0\0\0\0"
+  dstAddr="\xff\xff\xff\xff\xff\xff"
   proto = 0x8888
   zero = "\0\0"
-  def __init__ (self, localAddr="\x00\x00\x00\x00\x00\x00", remoteAddr="\xff\xff\xff\xff\xff\xff", proto=0x8888):
+  status = None
+  data = None
+
+  def __init__ (self, srcAddr="\x00\x00\x00\x00\x00\x00", dstAddr="\xff\xff\xff\xff\xff\xff", proto=0x8888):
     self.proto = proto
-    self.localAddr = localAddr
-    self.remoteAddr = remoteAddr
+    self.srcAddr = srcAddr
+    self.dstAddr = dstAddr
 
   def decode (self, data):
-    self.localAddr, self.remoteAddr, self.proto = struct.unpack(self.ethHeaderFmt,data[:14])
+    self.dstAddr, self.srcAddr, self.proto = struct.unpack(self.ethHeaderFmt,data[:14])
     if self.proto != 0x8888:
       # FIXME: Error message about invalid packet
       return False
@@ -244,16 +267,20 @@ class Ether8888Packet:
         struct.unpack (self.headerFmt, self.ethData[:10])
     self.payload = self.ethData[10:self.dataLen+10]
 
+    if (self.dataLen>2):
+      self.status = {"\0\0":True}.get( self.payload[:2])
+
     if (self.dataLen != len (self.payload)):
       # FIXME: Error message about invalid packet
       return False
+    self.data = self.payload[2:]
     return True
 
   def encode (self, cmd, unknown, nrPackets, dataLen, data):
     # Ethernet II header
     (self.cmd, self.unknown, self.nrPackets, self.dataLen,self.payload) = (cmd, unknown, nrPackets, dataLen, data)
     
-    d = struct.pack(self.ethHeaderFmt, self.remoteAddr, self.localAddr, self.proto)
+    d = struct.pack(self.ethHeaderFmt, self.dstAddr, self.srcAddr, self.proto)
     d += struct.pack (self.headerFmt, self.cmd, self.unknown, self.zero,
                       self.nrPackets, self.dataLen)
     d += data
@@ -261,7 +288,8 @@ class Ether8888Packet:
 
 class Ether8888DeviceFactory (DeviceFactory):
     supported_devices = (
-      {'desc':"Vonets VAP11G wireless bridge"},
+      {'id': '\x04\xE0\x54\x00', 'desc':"Vonets VAP11G wireless bridge"},
+      #{'id': '\x59\x4a\x34\x8c', 'desc':"HP2101nw Wireless USB print server (via WLAN)"},
     );
     proto=0x8888;
     def __init__ (self):
@@ -282,12 +310,12 @@ class Ether8888DeviceFactory (DeviceFactory):
 
         # Create Ethernet II broadcast socket of ethertype 0x8888:
         sockets = []
-        bcAddr = "\xFF\xFF\xFF\xFF\xFF\xFF";
+        bcAddr = "\xFF\xFF\xFF\xFF\xFF\xFF"
         for i in interfaces:
           s = socket.socket(socket.AF_PACKET, socket.SOCK_RAW, self.proto)
           s.bind((i,self.proto))
           ifName,ifProto,pktType,hwType,hwAddr = s.getsockname()
-          packet = Ether8888Packet (localAddr = hwAddr, remoteAddr = bcAddr)
+          packet = Ether8888Packet (srcAddr = hwAddr, dstAddr = bcAddr)
           request = packet.encode ("\0\0", "\0\0", 0, 0, "\0"*0x10)
           # Send and wait for response
           s.send (request)
@@ -300,9 +328,31 @@ class Ether8888DeviceFactory (DeviceFactory):
           for sock in sread:
             rxFrame = sock.recv (1500)
             pack = Ether8888Packet()
-            if pack.decode (rxFrame) and (not pack.remoteAddr == bcAddr):
-              ifName,ifProto,pktType,hwType,hwAddr = sock.getsockname()
-              devices.append (Ether8888Device (ui, ifName, ifProto, pack.localAddr, "Vonets VAP11G wireless bridge"));
+            # Decode frame and filter out all broadcasts (in case we have a
+            # loop, e.g. because the device is already connected to the WLAN
+            # and so all packages sent over eth0 will be received via the wlan
+            # bridge on the wireless interface!)
+            if (not pack.decode (rxFrame)):
+              ui.error ("decoding response packet of device detection")
+              continue
+            is_broadcast = (pack.srcAddr == bcAddr) and (pack.dstAddr == bcAddr)
+            if is_broadcast:
+              ui.debug ("Received broadcast package instead of response:")
+              ui.hex_print (rxFrame)
+              continue
+            ifName,ifProto,pktType,hwType,hwAddr = sock.getsockname()
+            devdesc = None
+            for d in self.supported_devices:
+              if d['id'] == pack.data[2:6]:
+                devdesc = d['desc']
+                break
+            else:
+              ui.hex_print (pack.srcAddr)
+              ui.progress ("Response received from unknown device (id {}, MAC {}, interface {})".format (formatHex2 (pack.data[2:6]), formatMAC (pack.srcAddr), ifName))
+              continue
+            ui.debug ("Received response packet:")
+            ui.hex_print (rxFrame)
+            devices.append (Ether8888Device (ui, ifName, ifProto, pack.srcAddr, devdesc, localAddr = pack.dstAddr));
         for s in sockets:
           s.close ();
 
@@ -325,20 +375,29 @@ class Ether8888Device (Device):
   proto = 0x8888;
   desc = ""
   socket = None
-  def __init__ (self, ui, iface, proto, mac, desc):
+  cmds = {'dev_info': "\x00\x00",
+          'dev_stat': "\x00\x01",
+          'send_data': "\x01\x01",
+          'recv_data': "\x02\x01"}
+  def __init__ (self, ui, iface, proto, mac, desc,localAddr = ""):
     Device.__init__ (self, ui);
     self.ifName = iface
     self.mac = mac
     self.proto = proto
     self.desc = desc
-    self.srcAddr = None
-    self.destAddr = None
+    self.localAddr = localAddr
+    self.remoteAddr = mac
     self.capabilities['wifi'] = True;
     self.capabilities['ad-hoc'] = False;
+    
+    self.ui.debug("localAddr: ")
+    self.ui.hex_print (self.localAddr)
+    self.ui.debug("remoteAddr: ")
+    self.ui.hex_print (self.remoteAddr)
 
   def device_string (self):
     return "%s (Ethernet interface %s, MAC %12s)" % (
-           self.desc, self.ifName, ':'.join('%02x' % ord(b) for b in self.mac));
+           self.desc, self.ifName, formatMAC (self.mac));
 
   def device_open (self):
     try:
@@ -350,7 +409,7 @@ class Ether8888Device (Device):
       self.error ("Error opening socket for device '%s' on interface '%s'; message: %s" % (self.desc, self.ifName, e.message))
       s.close ()
       return False
-    self.ui.progress ("Successfully opened socket for device '%s' on interface '%s'" % (self.desc, self.ifName))
+    self.ui.debug ("Successfully opened socket for device '%s' on interface '%s'" % (self.desc, self.ifName))
     return True;
 
   def device_close (self):
@@ -360,69 +419,87 @@ class Ether8888Device (Device):
 
   def device_reset (self):
     self.ui.progress ("Resetting the device, please wait")
-    res = self.command_send ("9002")
-    self.ui.debug ("\tSent 9002 reset command: %d" % res)
+    res = self.command_send ("9002:\n")
+    self.ui.debug ("\tSent 9002 reset command; response: %s (len: %d)" % (res, len(res)))
     # Poll the device until it doesn't respond. Then sleep for ~15 seconds
     self.ui.sleep_progress (20)
     self.device_close ()
     self.ui.wait_enter ("Device was reset. Please press Return.")
 
-  def bulk_data_write (self, data, length, cmd="\x01\x01", unknown="\0\0"):
-    packet = Ether8888Packet (localAddr = self.localAddr, remoteAddr = self.remoteAddr)
-    request = packet.encode (cmd, unknown, 0, length, data)
-    self.ui.debug ("Request: " + request)
+
+  def raw_write (self, data):
     res = None
     try:
-      res = self.socket.send (request)
+      res = self.socket.send (data)
     except Exception, e:
       self.error ("writing data; message: %s" % e.message)
     return res
 
-  # Read and return USB bulk data
-  def bulk_data_read (self, length, timeout=500):
-    # TODO: Get rid of the length argument, simply read all that is sent
-    try:
-      res = self.handle.bulkRead (2, length+13, timeout);
-    except Exception, e:
-      self.error ("reading bulk data; message: %s" % e.message)
-      return None
-
-    # bulkRead returns a tuple, convert to a binary string
-    res = ''.join(chr(v) for v in res)
-    if (len (res) == 0):
-      self.ui.debug ("\tEmpty response received\n")
-      return ''
+  def raw_read (self, length=15000, timeout=500):
+    self.ui.debug ("raw_read")
+    toread = 1 # Nr of remaining packets to read
+    data = None
+    while (toread>0):
+      (sread, swrite, sx) = select.select([self.socket], [], [], timeout/1000)
+      for sock in sread:
+        rxFrame = sock.recv (length)
+        toread -= 1
+        pack = Ether8888Packet(self.remoteAddr, self.localAddr, self.proto)
+        if pack.decode (rxFrame):
+          #self.ui.debug ("Complete returned data frame:")
+          #self.ui.hex_print (rxFrame)
+          toread = pack.nrPackets
+          if (not data):
+            data = ""
+          data += pack.data
+        else:
+          self.error ("decoding returned data: %s" % rxFrame)
+          self.ui.debug ("Unable to decode the %d bytes returned: \n" % len (rxFrame))
+          self.ui.hex_print (rxFrame)
+      if (len (sread) == 0 ):
+        self.error ("reading data, no response received")
+        toread = 0
+
+    #self.ui.debug ("Complete returned data:")
+    #self.ui.hex_print (data)
+    return data
+
+  def data_write (self, data, length, cmd=None, unknown="\x01\x00"):
+    self.ui.debug("data_write %d, %s"%(length, data))
+    if not cmd:
+      cmd = self.cmds.get('send_data')
+
+    packet = Ether8888Packet (srcAddr = self.localAddr, dstAddr = self.remoteAddr)
+    request = packet.encode (cmd, unknown, 0, length, data)
+    self.ui.debug ("Request: " + request)
+    res = self.raw_write (request)
+    time.sleep(1)
+    return self.raw_read ()
 
-    self.ui.debug ("read %d bytes: \n" % len (res))
-    self.ui.hex_print (res)
-    # Check and cut off the header after some sanity checks:
-    if (not res.startswith ("@\0\0")):
-      self.error ("reading data: Wrong header %s" % res[0:3])
-    (datalen,) = struct.unpack ("H", res[3:5]);
-    realdatalen = len (res)-13
-    if (datalen != realdatalen):
-      self.error ("reading data: Expected %d bytes of data, got %d\n" % (datalen, realdatalen))
-    self.boxname = res[5:13]
-    ## FIXME: Check the name of the box...
-    ## cut off the header:
-    return res[13:]
+  # Read and return USB bulk data
+  def data_read (self, length, timeout=500):
+    self.ui.debug("data_read %d"%length)
+    # TODO: Request return data
+    packet = Ether8888Packet (srcAddr = self.localAddr, dstAddr = self.remoteAddr)
+    request = packet.encode (self.cmds.get('recv_data'), "\x02\x00", 0, 0, "")
+    res = self.raw_write (request)
+    time.sleep (1)
+    return self.raw_read (length, timeout)
 
 
-TODO:
-  def command_send (self, cmd):
-    cfg = "%s:\n" % cmd
-    res = self.bulk_data_write (cfg, len(cfg), cmd="\x01\x01", unknown="\0\0")
-    return self.bulk_data_read (25600)
+  def command_send (self, cfg):
+    res = self.data_write (cfg, len(cfg), cmd=self.cmds.get('send_data'), unknown="\1\0")
+    return self.data_read (25600)
 
   def config_retrieve (self):
     self.ui.debug ("Reading current configuration...");
-    return self.command_send ("9100")
+    return self.command_send ("9100:\n")
 
   def config_send (self, config):
     self.ui.progress ("Sending new configuation to the device. Please wait")
     cfgstring = config.to_string ()
     self.ui.debug ("\tNew device config: %s\n" % cfgstring)
-    self.bulk_data_write (cfgstring, len(cfgstring), cmd="\0x02)
+    self.command_send (cfgstring)
     self.ui.sleep_progress (10)
     # Now reset the device:
     return self.device_reset ()
diff --git a/appliance_setup/helpers.py b/appliance_setup/helpers.py
index 0e26a92bfdd4b48e92077b5daae7877b70112350..da2038a4eb159137ba1ed79796a31d048de4f845 100755
--- a/appliance_setup/helpers.py
+++ b/appliance_setup/helpers.py
@@ -47,4 +47,30 @@ def find(f, seq):
   """Return first item in sequence where f(item) == True."""
   for item in seq:
     if f(item): 
-      return item
\ No newline at end of file
+      return item
+
+def formatMAC(m):
+  return ':'.join('%02x' % ord(b) for b in m)
+
+def formatHex2(d):
+  return "0x" + " ".join ('%02x' % ord(b) for b in d)
+
+def parse_survey_data (survey):
+  networks = {}
+  entries = filter (None, survey.split ("\x0b"))
+  for e in entries:
+    (ssid, settings) = e.split ("\x0c")
+    settings = settings.split (",")
+    # If device doesn't support ad-hoc, settings has only 4 entries => add dummy
+    if len(settings)<6:
+      settings.append (None)
+    networks[ssid] = {
+      'mac':     settings[0],
+      'channel': settings[1],
+      'wifi_ver':settings[2],
+      'secmode': settings[3],
+      'signal' : settings[4],
+      'adhoc':   settings[5]
+    }
+  return networks
+
diff --git a/appliance_setup/user_interface.py b/appliance_setup/user_interface.py
index 8a55de1062c2f9f83b520a4d660977d017d9569d..71fce11894bc5ba48dc07f4251a4806b68747d9e 100755
--- a/appliance_setup/user_interface.py
+++ b/appliance_setup/user_interface.py
@@ -43,8 +43,28 @@ class UserInterface:
     pass
   def display_device_settings (self):
     pass
-  def print_wireless_networks (self):
-    pass
+  # Print a table of available wifi networks
+  def print_wireless_networks (self, aps):
+    pass
+  # Request a wifi network from the user. First, show the table of APs,
+  # then ask. It's also possible to let the user enter the SSID of a hidden
+  # network.
+  def ask_wireless_ap (self, aps):
+    pass
+  # Request IP Address settings (DHCP, IP, netmask, gateway); returns a dict
+  def ask_IP_setting (self):
+    dhcp = self.ask_choice ("IP-address assignment:", ["DHCP", "Manual"], ["Enable", "Disable"], "Enable");
+    result = {"dhcp": dhcp}
+    if (dhcp == "Enable");
+      result['ip_addr'] = self.ask_ip_address ("IP-address of the device:")
+      result['mask']    = self.ask_ip_address ("Netmask:")
+      result['gateway'] = self.ask_ip_address ("IP-address of the gateway:")
+    else:
+      result['ip_addr'] = "0.0.0.0"
+      result['mask']    = "0.0.0.0"
+      result['gateway'] = "0.0.0.0"
+    return result
+
   def ask_operation (self):
     pass
   def ask_ip_address (self, string):
@@ -85,12 +105,12 @@ class ConsoleInterface (UserInterface):
       if (i % 8 == 0):
         line += " "
       if (i % 16 == 0):
-        print ("0x%04x  %34s  %16s" % (index, line, readable))
+        print ("{:#06x}  {:<50}  {:<16}".format (index, line, readable))
         index += 0x10;
         readable = ""
         line = ""
     if (len (line) > 0):
-      print ("0x%04x  %34s  %16s" % (index, line, readable))
+      print ("{:#06x}  {:<50}  {:<16}".format (index, line, readable))
     sys.stdout.flush()
 
   def input (self, str):
@@ -150,8 +170,6 @@ class ConsoleInterface (UserInterface):
 
   def display_device_settings (self):
     pass
-  def print_wireless_networks (self):
-    pass
   def ask_operation (self):
     pass
 
@@ -165,4 +183,60 @@ class ConsoleInterface (UserInterface):
       "\tInvalid key %s. Length can only be 10 or 26, use only digits 0-9 and letters a-f.\n\n")
 
   def wait_enter (self, text):
-    raw_input (text)
\ No newline at end of file
+    raw_input (text)
+
+  def print_wireless_networks (self, aps):
+    fmt = "    %3s %-25s%-9s%-13s%-17s%-8s\n"
+    msg = "Detected wireless networks:\n"
+    msg += fmt % ("   ", "SSID", "Signal", "Security", "Type", "channel")
+    msg += "\t------------------------------------------------------------------------\n"
+    i = 0
+    ssids = aps.keys()
+    ssids.sort (key=str.lower)
+    for ssid in ssids:
+      i += 1
+      network = aps.get (ssid, {})
+      msg += fmt % (str(i)+")", ssid, network.get ('signal', ''),
+                    security2string (network.get ('secmode', '')),
+                    "Ad-Hoc" if network.get ('adhoc', None) else "Infrastructure",
+                    network.get ('channel', ''))
+    print msg
+
+  def ask_wireless_ap (self, aps):
+    self.print_wireless_networks (aps)
+    ssids = aps.keys()
+    ssids.sort (key=str.lower)
+
+    print "Please enter the number or the SSID of the desired wireless network."
+    print "\tEnter '0', 'hidden' or 'h' to connect to a hidden network."
+    print "\tEnter 'r' or 'rescan' to rescan for wireless networks."
+
+    newssid = None
+    while (not newssid):
+      newssid = self.input ("Desired wireless network: ")
+    print "Newssid=%s" % newssid
+    if aps.get (newssid):
+      print "Known SSID %s" % newssid
+      return newssid
+    if (newssid == 'h' or newssid == 'hidden' or newssid == '0'):
+      newssid = ''
+      while (not newssid):
+        newssid = self.input ("Please enter the hidden network name:")
+      return newssid
+    if (newssid == 'r' or newssid == 'rescan'):
+      print "Rescan (%s)" % newssid
+      return None
+
+    try:
+      i = int(newssid)
+      print "int %s  = %d" % (newssid,i)
+      if (i>0 and i<len(ssids)):
+        print "In range"
+        return ssids[i-1]
+      else:
+        print "Not in range"
+    except Exception, e:
+      print e.message
+      return self.ask_wireless_ap (aps)
+
+