merging in (some of) Daniel's GPIO pin stuff
diff --git a/bbb_cape/src/bbb/bbb.gyp b/bbb_cape/src/bbb/bbb.gyp
index 1722bce..86bad66 100644
--- a/bbb_cape/src/bbb/bbb.gyp
+++ b/bbb_cape/src/bbb/bbb.gyp
@@ -130,6 +130,7 @@
         'packet_finder',
         'data_struct',
         '<(AOS)/common/common.gyp:time',
+        'gpios',
       ],
     },
     {
@@ -137,6 +138,8 @@
       'type': 'static_library',
       'sources': [
         'gpios.cc',
+        'gpi.cc',
+        'gpo.cc',
       ],
       'dependencies': [
         '<(AOS)/build/aos.gyp:logging',
diff --git a/bbb_cape/src/bbb/byte_reader.h b/bbb_cape/src/bbb/byte_reader.h
index 16e364c..80bb208 100644
--- a/bbb_cape/src/bbb/byte_reader.h
+++ b/bbb_cape/src/bbb/byte_reader.h
@@ -8,11 +8,11 @@
 namespace bbb {
 
 class ByteReader {
- public:
+public:
   // We have 64-bit ints in some of our data.
   typedef char __attribute__((aligned(8))) AlignedChar;
 
-  // Implemented by subclasses to provide a data source 
+  // Implemented by subclasses to provide a data source
   // for these algorithms.
   // Returns the number of bytes read, -1 if there is an error in errno, or -2
   // if reading takes longer than timeout.
diff --git a/bbb_cape/src/bbb/gpi.cc b/bbb_cape/src/bbb/gpi.cc
new file mode 100644
index 0000000..90c46d5
--- /dev/null
+++ b/bbb_cape/src/bbb/gpi.cc
@@ -0,0 +1,48 @@
+#include "gpi.h"
+
+#include <stdio.h>
+
+#include "aos/common/logging/logging.h"
+
+namespace bbb {
+
+Gpi::Gpi(int bank, int pin) {
+  // All the failures here are fatal, seeing as
+  // if we can't initialize the pin, we're
+  // probably screwed anyway.
+  if (!InitPin(bank, pin)) {
+    LOG(FATAL, "Failed to export pin.\n");
+  }
+  if (!DoPinDirSet(1)) {
+    LOG(FATAL, "Failed to set pin as an input.\n");
+  }
+}
+
+int Gpi::Read() {
+  // NOTE: I can't find any docs confirming that one can indeed
+  // poll a pin's value using this method, but it seems that it
+  // should work. Really, the "right" (interrupt driven) way to
+  // do this is to set an event, but that involves messing with
+  // dev tree crap, which I'm not willing to do unless we need
+  // this functionality.
+  char buf, val_path[64];
+  snprintf(val_path, sizeof(val_path), "/sys/class/gpio/gpio%d/value",
+           kernel_pin_);
+
+  if ((handle_ = fopen(val_path, "rb")) == NULL) {
+    LOG(ERROR, "Unable to open file for pin value reading.\n");
+    fclose(handle_);
+    return -1;
+  }
+
+  if (fread(&buf, sizeof(char), 1, handle_) <= 1) {
+    LOG(ERROR, "Reading from file failed with error %d\n",
+        ferror(handle_));
+    fclose(handle_);
+    return -1;
+  }
+  fclose(handle_);
+  return atoi(&buf);
+}
+
+}  // namespace bbb
diff --git a/bbb_cape/src/bbb/gpi.h b/bbb_cape/src/bbb/gpi.h
new file mode 100644
index 0000000..be41a11
--- /dev/null
+++ b/bbb_cape/src/bbb/gpi.h
@@ -0,0 +1,23 @@
+#ifndef BBB_CAPE_SRC_BBB_GPI_H_
+#define BBB_CAPE_SRC_BBB_GPI_H_
+
+#include "gpios.h"
+
+// Subclass of Pin for input pins.
+
+namespace bbb {
+
+class Gpi : public Pin {
+ public:
+  // See the base class for what these args mean.
+  Gpi(int bank, int pin);
+
+  // Read the current value of the pin.
+  // Returns 1 if it reads high, 0 for low.
+  // Returns -1 if fails to read the pin for some reason.
+  int Read();
+};
+
+}  // namespace bbb
+
+#endif
diff --git a/bbb_cape/src/bbb/gpios.cc b/bbb_cape/src/bbb/gpios.cc
index 5a9c76e..8594ba4 100644
--- a/bbb_cape/src/bbb/gpios.cc
+++ b/bbb_cape/src/bbb/gpios.cc
@@ -7,147 +7,62 @@
 
 namespace bbb {
 
-Pin::Pin(int bank, int pin)
-    : handle_(NULL),
-      direction_(0),
-      kernel_pin_(bank * 32 + pin),
-      exported_(false) {}
+Pin::Pin() {}
 
 Pin::~Pin() {
   // Unexport the pin.
   if ((handle_ = fopen("/sys/class/gpio/unexport", "ab")) == NULL) {
-    LOG(WARNING, "Could not unexport gpio pin.\n");
+    LOG(WARNING, "Could not open file to unexport pin.\n");
     // There's nothing intelligent we can really do here.
     return;
   }
 
-  char gpio_num[2];
-  snprintf(gpio_num, sizeof(gpio_num), "%d", kernel_pin_);
-  fwrite(gpio_num, sizeof(char), 2, handle_);
+  fprintf(handle_, "%d", kernel_pin_);
   fclose(handle_);
 }
 
-int Pin::DoExport() {
-  char gpio_num[2];
-  snprintf(gpio_num, sizeof(gpio_num), "%d", kernel_pin_);
+bool Pin::InitPin(int bank, int pin) {
+  kernel_pin_ = bank * 32 + pin;
 
   // Export the pin.
   if ((handle_ = fopen("/sys/class/gpio/export", "ab")) == NULL) {
-    LOG(ERROR, "Could not export GPIO pin.\n");
-    return -1;
+    LOG(ERROR, "Could not open file for exporting pin.\n");
+    return false;
   }
 
-  fwrite(gpio_num, sizeof(char), 2, handle_);
+  fprintf(handle_, "%d", kernel_pin_);
   fclose(handle_);
-
-  exported_ = true;
-  return 0;
+  return true;
 }
 
-int Pin::DoPinDirSet(int direction) {
-  char buf[4], type_path[64];
+bool Pin::DoPinDirSet(int direction) {
+  char type_path[64];
   snprintf(type_path, sizeof(type_path), "/sys/class/gpio/gpio%d/direction",
            kernel_pin_);
 
   if ((handle_ = fopen(type_path, "rb+")) == NULL) {
-    LOG(ERROR, "Unable to set pin direction.\n");
-    return -1;
+    LOG(ERROR, "Unable open file for pin direction setting.\n");
+    return false;
   }
 
-  direction_ = direction;
   switch (direction) {
     case 1:
-      strcpy(buf, "in");
+      // Input.
+      fprintf(handle_, "in");
       break;
     case 2:
-      strcpy(buf, "low");
+      // Output.
+      // If it's an output, we should specify an initial direction.
+      fprintf(handle_, "low");
       break;
-    case 0:
-      return 0;
     default:
       LOG(ERROR, "Invalid direction identifier %d.\n", direction);
-      direction_ = 0;
-      return -1;
+      fclose(handle_);
+      return false;
   }
-  fwrite(buf, sizeof(char), 3, handle_);
+
   fclose(handle_);
-
-  return 0;
-}
-
-int Pin::MakeInput() {
-  if (!exported_) {
-    if (DoExport()) {
-      return -1;
-    }
-  }
-
-  return DoPinDirSet(1);
-}
-
-int Pin::MakeOutput() {
-  if (!exported_) {
-    if (DoExport()) {
-      return -1;
-    }
-  }
-
-  return DoPinDirSet(2);
-}
-
-int Pin::Write(uint8_t value) {
-  if (direction_ != 2) {
-    LOG(ERROR, "Only pins set as output can be written to.\n");
-    return -1;
-  }
-
-  char buf, val_path[64];
-  snprintf(val_path, sizeof(val_path), "/sys/class/gpio/gpio%d/value",
-           kernel_pin_);
-  if (value != 0) {
-    value = 1;
-  }
-
-  if ((handle_ = fopen(val_path, "rb+")) == NULL) {
-    LOG(ERROR, "Unable to set pin value.\n");
-    return -1;
-  }
-
-  snprintf(&buf, sizeof(buf), "%d", value);
-  fwrite(&buf, sizeof(char), 1, handle_);
-  fclose(handle_);
-
-  return 0;
-}
-
-int Pin::Read() {
-  // NOTE: I can't find any docs confirming that one can indeed
-  // poll a pin's value using this method, but it seems that it
-  // should work. Really, the "right" (interrupt driven) way to
-  // do this is to set an event, but that involves messing with
-  // dev tree crap, which I'm not willing to do unless we need
-  // this functionality.
-
-  if (direction_ != 1) {
-    LOG(ERROR, "Only pins set as input can be read from.\n");
-    return -1;
-  }
-
-  char buf, val_path[64];
-  snprintf(val_path, sizeof(val_path), "/sys/class/gpio/gpio%d/value",
-           kernel_pin_);
-
-  if ((handle_ = fopen(val_path, "rb")) == NULL) {
-    LOG(ERROR, "Unable to read pin value.\n");
-    return -1;
-  }
-
-  if (fread(&buf, sizeof(char), 1, handle_) <= 0) {
-    LOG(ERROR, "Failed to read pin value from file.\n");
-    return -1;
-  }
-  fclose(handle_);
-  return atoi(&buf);
+  return true;
 }
 
 }  // namespace bbb
diff --git a/bbb_cape/src/bbb/gpios.h b/bbb_cape/src/bbb/gpios.h
index a377d68..4925f1b 100644
--- a/bbb_cape/src/bbb/gpios.h
+++ b/bbb_cape/src/bbb/gpios.h
@@ -1,38 +1,46 @@
 #ifndef BBB_CAPE_SRC_BBB_CAPE_CONTROL_H_
 #define BBB_CAPE_SRC_BBB_CAPE_CONTROL_H_
 
-#include <stdint.h>
 #include <stdio.h>
 
+#include "aos/common/macros.h"
+
 // As it turns out, controlling the BBB's GPIO pins
 // from C++ is kind of a pain. The purpose of this
 // code is to provide a simple wrapper that masks
 // all the ugly stuff and exposes a nice API.
 
-// Based on example from 
+// Based on example from
 // <http://learnbuildshare.wordpress.com/2013/05/29/beaglebone-black-digital-ouput/>
 
+// This is a base class for all gpio related stuff.
+// Use either a gpi or gpo subclass if you want to do things.
 namespace bbb {
 
 class Pin {
-  FILE *handle_;
-  int direction_;
-  int kernel_pin_;
-  bool exported_;
+ public:
+  // Not strictly necessary for this to be virtual,
+  // but it's a good idea.
+  virtual ~Pin();
+  // When you don't define this and use the 
+  // DISALLOW_COPY_AND_ASSIGN macro, the compiler
+  // doesn't seem to create a default one.
+  Pin();
 
-  int DoPinDirSet(int direction);
-  int DoExport();
-
-public:
+ protected:
+  // Set the pin direction.
+  // 1 makes it an input.
+  // 2 makes it an output and sets the initial state to low.
+  bool DoPinDirSet(int direction);
+  // Export the pin, so we can use it.
   // Here, for example, if you wanted to use
-  // GPIO1_28, you would give the ctor
-  // 1, 28 as arguments.
-  Pin(int bank, int pin);
-  ~Pin();
-  int MakeInput();
-  int MakeOutput();
-  int Write(uint8_t value);
-  int Read();
+  // GPIO1_28, you would give it 1, 28 as arguments.
+  bool InitPin(int bank, int pin);
+
+  FILE *handle_ = NULL;
+  int kernel_pin_ = -1;
+
+  DISALLOW_COPY_AND_ASSIGN(Pin);
 };
 
 }  // namespace bbb
diff --git a/bbb_cape/src/bbb/gpo.cc b/bbb_cape/src/bbb/gpo.cc
new file mode 100644
index 0000000..959b132
--- /dev/null
+++ b/bbb_cape/src/bbb/gpo.cc
@@ -0,0 +1,37 @@
+#include "gpo.h"
+
+#include <stdio.h>
+
+#include "aos/common/logging/logging.h"
+
+namespace bbb {
+
+Gpo::Gpo(int bank, int pin) {
+  // All the failures here are fatal, seeing as
+  // failure to initialize the pin would at best
+  // severely cripple the calling process.
+  if (!InitPin(bank, pin)) {
+    LOG(FATAL, "Failed to export the pin.\n");
+  }
+  if (!DoPinDirSet(2)) {
+    LOG(FATAL, "Failed to make the pin an output.\n");
+  }
+}
+
+bool Gpo::Set(const bool high) {
+  char val_path[64];
+  snprintf(val_path, sizeof(val_path), "/sys/class/gpio/gpio%d/value",
+           kernel_pin_);
+
+  if ((handle_ = fopen(val_path, "rb+")) == NULL) {
+    LOG(ERROR, "Unable open file for pin value setting.\n");
+    return false;
+  }
+
+  fprintf(handle_, "%d", high);
+  fclose(handle_);
+
+  return true;
+}
+
+}  // namespace bbb
diff --git a/bbb_cape/src/bbb/gpo.h b/bbb_cape/src/bbb/gpo.h
new file mode 100644
index 0000000..596daf5
--- /dev/null
+++ b/bbb_cape/src/bbb/gpo.h
@@ -0,0 +1,22 @@
+#ifndef BBB_CAPE_SRC_BBB_GPO_H_
+#define BBB_CAPE_SRC_BBB_GPO_H_
+
+#include "gpios.h"
+
+namespace bbb {
+
+// Gpios subclass for output pins.
+class Gpo : public Pin {
+ public:
+  // See the base class for what these args mean.
+  Gpo(int bank, int pin);
+  // Sets the pin to either high or low.
+  // If the argument is true, is sets it high.
+  // Otherwise, it sets it low.
+  bool Set(const bool high);
+
+};
+
+}  // namespace bbb
+
+#endif