summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRobert Quattlebaum <rquattle@google.com>2017-11-22 17:24:33 -0800
committerRobert Quattlebaum <rquattle@google.com>2017-11-22 17:25:37 -0800
commitc47e2c6a99ddad9497bc3b390c47e363f38e11a4 (patch)
tree72c7da3071bdc87b651a7f5d91b6c9ee54b4e6c9
parent1ed605b98876dc15df2f3a946f61a07ca161b392 (diff)
downloadlowpan-c47e2c6a99ddad9497bc3b390c47e363f38e11a4.tar.gz
lowpan_hdlc_adapter: Wait for Event::OPENED before calling sendFrame()
Part of the LoWPAN HAL contract is that the user of the device interface will wait until it receives LowpanEvent::OPENED before calling sending frames using the interface. The LoWPAN HDLC Adapter was breaking that contract, calling sendFrame pretty much immediately after calling open. This change makes sure that we wait for the OPENED event before calling sendFrame(). If we receive an ERROR event first, then we terminate. Bug: b/69687483 Change-Id: I6e0574dbda00775eab6fe8a8c617521e4c48c8cc
-rw-r--r--lowpan_hdlc_adapter/lowpan_hdlc_adapter.cpp50
1 files changed, 45 insertions, 5 deletions
diff --git a/lowpan_hdlc_adapter/lowpan_hdlc_adapter.cpp b/lowpan_hdlc_adapter/lowpan_hdlc_adapter.cpp
index c47094b..6986b2f 100644
--- a/lowpan_hdlc_adapter/lowpan_hdlc_adapter.cpp
+++ b/lowpan_hdlc_adapter/lowpan_hdlc_adapter.cpp
@@ -20,6 +20,9 @@
#include <unistd.h>
+#include <mutex>
+#include <condition_variable>
+
#include <hidl/HidlTransportSupport.h>
#include <hidl/ServiceManagement.h>
#include <hidl/Status.h>
@@ -54,11 +57,22 @@ struct LowpanDeathRecipient : hidl_death_recipient {
struct LowpanDeviceCallback : public ILowpanDeviceCallback {
int mFd;
+ std::mutex mMutex;
+ std::condition_variable mConditionVariable;
+ int mOpenError;
static const uint32_t kMaxFrameSize = LOWPAN_HDLC_ADAPTER_MAX_FRAME_SIZE;
public:
- LowpanDeviceCallback(int fd): mFd(fd) { }
+ LowpanDeviceCallback(int fd): mFd(fd), mOpenError(-1) {}
virtual ~LowpanDeviceCallback() = default;
+ int waitForOpenStatus() {
+ std::unique_lock<std::mutex> lock(mMutex);
+ if (mOpenError == -1) {
+ mConditionVariable.wait(lock);
+ }
+ return mOpenError;
+ }
+
Return<void> onReceiveFrame(const hidl_vec<uint8_t>& data) override {
if (data.size() > kMaxFrameSize) {
ALOGE("TOOBIG: Frame received from device is too big");
@@ -84,6 +98,8 @@ public:
buffer[bufferIndex++] = HDLC_BYTE_FLAG;
+ std::unique_lock<std::mutex> lock(mMutex);
+
if (write(mFd, buffer, bufferIndex) != bufferIndex) {
ALOGE("IOFAIL: write: %s (%d)", strerror(errno), errno);
exit(EXIT_FAILURE);
@@ -93,13 +109,20 @@ public:
}
Return<void> onEvent(LowpanEvent event, LowpanStatus status) override {
+ std::unique_lock<std::mutex> lock(mMutex);
+
switch (event) {
case LowpanEvent::OPENED:
+ if (mOpenError == -1) {
+ mOpenError = 0;
+ mConditionVariable.notify_all();
+ }
ALOGI("Device opened");
break;
case LowpanEvent::CLOSED:
ALOGI("Device closed");
+ exit(EXIT_SUCCESS);
break;
case LowpanEvent::RESET:
@@ -107,6 +130,10 @@ public:
break;
case LowpanEvent::ERROR:
+ if (mOpenError == -1) {
+ mOpenError = int(status);
+ mConditionVariable.notify_all();
+ }
switch (status) {
case LowpanStatus::IOFAIL:
ALOGE("IOFAIL: Input/Output error from device. Terminating.");
@@ -137,10 +164,18 @@ class ReadThread : public Thread {
int mBufferIndex;
bool mUnescapeNextByte;
uint16_t mFcs;
+ sp<LowpanDeviceCallback> mCallback;
public:
- ReadThread(sp<ILowpanDevice> service, int fd):
- Thread(false /*canCallJava*/), kReadThreadBufferSize(service->getMaxFrameSize()), mService(service), mFd(fd), mBufferIndex(0), mUnescapeNextByte(false),mFcs(kHdlcCrcResetValue) {
+ ReadThread(sp<ILowpanDevice> service, int fd, sp<LowpanDeviceCallback> callback):
+ Thread(false /*canCallJava*/),
+ kReadThreadBufferSize(service->getMaxFrameSize()),
+ mService(service),
+ mFd(fd),
+ mBufferIndex(0),
+ mUnescapeNextByte(false),
+ mFcs(kHdlcCrcResetValue),
+ mCallback(callback) {
if (kReadThreadBufferSize < 16) {
ALOGE("Device returned bad max frame size: %d bytes", kReadThreadBufferSize);
exit(EXIT_FAILURE);
@@ -157,6 +192,11 @@ private:
bool threadLoop() override {
uint8_t buffer[LOWPAN_HDLC_ADAPTER_MAX_FRAME_SIZE];
+ if (int error = mCallback->waitForOpenStatus()) {
+ ALOGE("Call to `open()` failed: %d", error);
+ exit(EXIT_FAILURE);
+ }
+
while (!exitPending()) {
ssize_t bytesRead = read(mFd, buffer, sizeof(buffer));
if (exitPending()) {
@@ -250,7 +290,7 @@ int main(int argc, char* argv []) {
configureRpcThreadpool(1, true /* callerWillJoin */);
- sp<ILowpanDeviceCallback> callback = new LowpanDeviceCallback(STDOUT_FILENO);
+ sp<LowpanDeviceCallback> callback = new LowpanDeviceCallback(STDOUT_FILENO);
{
auto status = service->open(callback);
@@ -267,7 +307,7 @@ int main(int argc, char* argv []) {
}
}
- sp<Thread> readThread = new ReadThread(service, STDIN_FILENO);
+ sp<Thread> readThread = new ReadThread(service, STDIN_FILENO, callback);
readThread->run("ReadThread");