From 6c3a7808db2ba7d3699aaa4c813da4eea810e577 Mon Sep 17 00:00:00 2001 From: Paul Nettle Date: Mon, 2 Oct 2017 11:02:09 -0500 Subject: Improved threading support, cleaner initialization process and added the ability to wait for threaded responses from HCI commands. --- src/HciAdapter.h | 82 ++++++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 62 insertions(+), 20 deletions(-) (limited to 'src/HciAdapter.h') diff --git a/src/HciAdapter.h b/src/HciAdapter.h index a19d395..ad4f62a 100644 --- a/src/HciAdapter.h +++ b/src/HciAdapter.h @@ -37,9 +37,12 @@ #include #include #include +#include +#include #include "HciSocket.h" #include "Utils.h" +#include "Logger.h" namespace ggk { @@ -51,6 +54,9 @@ public: // Constants // + // How long to wait for a response event for commands sent to the adapter + static const int kMaxEventWaitTimeMS = 1000; + // A constant referring to a 'non-controller' (for commands that do not require a controller index) static const uint16_t kNonController = 0xffff; @@ -130,6 +136,15 @@ public: uint16_t commandCode; uint8_t status; + CommandCompleteEvent(const std::vector &data) + { + *this = *reinterpret_cast(data.data()); + toHost(); + + // Log it + Logger::debug(debugText()); + } + void toNetwork() { header.toNetwork(); @@ -161,6 +176,15 @@ public: uint16_t commandCode; uint8_t status; + CommandStatusEvent(const std::vector &data) + { + *this = *reinterpret_cast(data.data()); + toHost(); + + // Log it + Logger::debug(debugText()); + } + void toNetwork() { header.toNetwork(); @@ -194,6 +218,15 @@ public: uint32_t flags; uint16_t eirDataLength; + DeviceConnectedEvent(const std::vector &data) + { + *this = *reinterpret_cast(data.data()); + toHost(); + + // Log it + Logger::debug(debugText()); + } + void toNetwork() { header.toNetwork(); @@ -235,6 +268,15 @@ public: uint8_t addressType; uint8_t reason; + DeviceDisconnectedEvent(const std::vector &data) + { + *this = *reinterpret_cast(data.data()); + toHost(); + + // Log it + Logger::debug(debugText()); + } + void toNetwork() { header.toNetwork(); @@ -378,8 +420,8 @@ public: { std::string text = ""; text += "> Local name information\n"; - text += " + Name : '" + std::string(name) + "\n"; - text += " + Short name : '" + std::string(shortName); + text += " + Name : '" + std::string(name) + "'\n"; + text += " + Short name : '" + std::string(shortName) + "'"; return text; } } __attribute__((packed)); @@ -395,11 +437,10 @@ public: return instance; } - AdapterSettings getAdapterSettings(); - ControllerInformation getControllerInformation(); - VersionInformation getVersionInformation(); - LocalName getLocalName(); - + AdapterSettings getAdapterSettings() { return adapterSettings; } + ControllerInformation getControllerInformation() { return controllerInformation; } + VersionInformation getVersionInformation() { return versionInformation; } + LocalName getLocalName() { return localName; } int getActiveConnectionCount() { return activeConnections; } // @@ -415,26 +456,19 @@ public: // milliseconds. Therefore, it is not recommended attempt to retrieve the results from their accessors immediately. void sync(uint16_t controllerIndex); - // Connects the HCI socket if a connection does not already exist + // Connects the HCI socket if a connection does not already exist and starts the run thread // - // If a connection already exists, this method will do nothing and return true. + // If a connection already exists, this method will fail // // Note that it shouldn't be necessary to connect manually; any action requiring a connection will automatically connect // // Returns true if the HCI socket is connected (either via a new connection or an existing one), otherwise false - bool connect(); - - // Returns true if connected to the HCI socket, otherwise false - // - // Note that it shouldn't be necessary to connect manually; any action requiring a connection will automatically connect - bool isConnected() const; + bool start(); - // Disconnects from the HCI Socket - // - // If the connection is not connected, this method will do nothing. + // Waits for the HciAdapter run thread to join // - // It isn't necessary to disconnect manually; the HCI socket will get disocnnected automatically upon destruction - void disconnect(); + // This method will block until the thread joins + void stop(); // Sends a command over the HCI socket // @@ -453,6 +487,11 @@ private: // Private constructor for our Singleton HciAdapter() : activeConnections(0) {} + // Uses a std::condition_variable to wait for a response event for the given `commandCode` or `timeoutMS` milliseconds. + // + // Returns true if the response event was received for `commandCode` or false if the timeout expired. + bool waitFor(uint16_t commandCode, int timeoutMS); + // Our HCI Socket, which allows us to talk directly to the kernel HciSocket hciSocket; @@ -465,6 +504,9 @@ private: VersionInformation versionInformation; LocalName localName; + std::condition_variable conditionalWait; + int conditionalValue; + // Our active connection count int activeConnections; }; -- cgit v1.2.3