--- a/libupnpp/control/discovery.hxx
+++ b/libupnpp/control/discovery.hxx
@@ -23,6 +23,7 @@
 
 #include <string>
 #include <functional>
+#include <unordered_map>
 
 namespace UPnPClient {
 class UPnPDeviceDesc;
@@ -37,14 +38,14 @@
  * Manage UPnP discovery and maintain a directory of active devices. Singleton.
  *
  *
- * The service is initialize on the first call, starting
+ * The service is initialized on the first call, starting
  * the message-handling thread, registering our message handlers,
  * and initiating an asynchronous UPnP device search.
  *
  * The search implies a timeout period (the specified interval
  * over which the servers will send replies at random points). Any
  * subsequent traverse() call will block until the timeout
- * is expired. Use getRemainingDelay() to know the current
+ * is expired. Use getRemainingDelayMs() to know the current
  * remaining delay, and use it to do something else.
  *
  * We need a separate thread to process the messages coming up
@@ -52,35 +53,42 @@
  * calls to libupnp, and this must not be done from the libupnp
  * thread context which reported the initial message.
  * So there are three threads in action:
- *  - the reporting thread from libupnp.
- *  - the discovery service processing thread, which also runs the callbacks.
- *  - the user thread (typically the main thread), which calls traverse.
+ *  - The reporting thread from libupnp.
+ *  - The discovery service processing thread, which also runs the callbacks.
+ *  - The user thread (typically the main thread), which calls traverse.
  */
 class UPnPDeviceDirectory {
 public:
     /** Retrieve the singleton object for the discovery service,
-     * and possibly start it up if this is the first call. This does not wait
-     * significantly, a subsequent traverse() will wait until the
-     * initial delay is consumed.
+     * and possibly start it up if this is the first call. This does 
+     * not wait significantly: a subsequent traverse() will wait until 
+     * the initial delay is consumed. 2 S is libupnp MIN_SEARCH_WAIT, 
+     * I don't see much reason to use more
      */
-    static UPnPDeviceDirectory *getTheDir(time_t search_window = 3);
+    static UPnPDeviceDirectory *getTheDir(time_t search_window = 2);
 
     /** Clean up before exit. Do call this.*/
     static void terminate();
 
+    /** Type of user callback functions used for reporting devices and
+     * services */
     typedef std::function<bool (const UPnPDeviceDesc&,
-                               const UPnPServiceDesc&)> Visitor;
+                                const UPnPServiceDesc&)> Visitor;
 
     /** Possibly wait for the end of the initial delay, then traverse
-       the directory and call Visitor for each device/service pair */
+     * the directory and call Visitor for each device/service pair */
     bool traverse(Visitor);
 
-    /** Remaining time until current search complete */
+    /** Remaining milliseconds until current search complete. */
     time_t getRemainingDelayMs();
+    /** Remaining seconds until current search complete. Better use
+     * getRemainingDelayMs(), this is kept only for compatibility. */
     time_t getRemainingDelay();
 
     /** Set a callback to be called when devices report their existence
-     *  The visitor will be called once per device, with an empty service.
+     *  The function will be called once per device, with an empty service,
+     *  Note that calls to v may be performed from a separate thread
+     *  and some may occur before addCallback() returns.
      */
     static unsigned int addCallback(Visitor v);
     static void delCallback(unsigned int idx);
@@ -89,7 +97,11 @@
      *
      * This will wait for the remaining duration of the search window if the 
      * device is not found at once.
-     * Note that "friendly names" are not necessarily unique.
+     * Note that "friendly names" are not necessarily unique. The method will
+     * return a random instance (the first found) if there are several.
+     * @param fname the device UPnP "friendly name" to be looked for
+     * @param[out] ddesc the description data if the device was found.
+     * @return true if the name was found, else false.
      */
     bool getDevByFName(const std::string& fname, UPnPDeviceDesc& ddesc);
 
@@ -97,44 +109,34 @@
      *
      * This will wait for the remaining duration of the search window if the 
      * device is not found at once.
+     * @param udn the device Unique Device Name, a UUID.
+     * @param[out] ddesc the description data if the device was found.
+     * @return true if the device was found, else false.
      */
     bool getDevByUDN(const std::string& udn, UPnPDeviceDesc& ddesc);
 
+    /** Helper function: retrieve all description data for a  named device 
+     *  @param uidOrFriendly device identification. First tried as UUID then 
+     *      friendly name.
+     *  @param[output] deviceXML device description document.
+     *  @param[output] srvsXML service name - service description map.
+     *  @return true for success.
+     */
+    bool getDescriptionDocuments(
+        const std::string &uidOrFriendly, std::string& deviceXML,
+        std::unordered_map<std::string, std::string>& srvsXML);
+
+    
     /** My health */
-    bool ok() {
-        return m_ok;
-    }
+    bool ok();
+
     /** My diagnostic if health is bad */
-    const std::string getReason() {
-        return m_reason;
-    }
+    const std::string getReason();
 
 private:
-    UPnPDeviceDirectory(time_t search_window);
     UPnPDeviceDirectory(const UPnPDeviceDirectory &);
     UPnPDeviceDirectory& operator=(const UPnPDeviceDirectory &);
-
-    // Start UPnP search and record start of timeout
-    bool search();
-    // Look at the current pool and remove expired entries
-    void expireDevices();
-
-    // This is called by the thread which processes the device events
-    // when a new device appears. It wakes up any thread waiting for a
-    // device.
-    bool deviceFound(const UPnPDeviceDesc&, const UPnPServiceDesc&);
-
-    // Lookup a device in the pool. If not found and a search is active,
-    // use a cond_wait to wait for device events (awaken by deviceFound).
-    bool getDevBySelector(bool cmp(const UPnPDeviceDesc&, const std::string&),
-                          const std::string& value, UPnPDeviceDesc& ddesc);
-
-    static void *discoExplorer(void *);
-
-    bool m_ok;
-    std::string m_reason;
-    int m_searchTimeout;
-    time_t m_lastSearch;
+    UPnPDeviceDirectory(time_t search_window);
 };
 
 } // namespace UPnPClient