Project import
diff --git a/peripheralmanager/.clang-format b/peripheralmanager/.clang-format
new file mode 120000
index 0000000..f412743
--- /dev/null
+++ b/peripheralmanager/.clang-format
@@ -0,0 +1 @@
+../../build/tools/brillo-clang-format
\ No newline at end of file
diff --git a/peripheralmanager/Android.mk b/peripheralmanager/Android.mk
new file mode 100644
index 0000000..178cb8a
--- /dev/null
+++ b/peripheralmanager/Android.mk
@@ -0,0 +1,17 @@
+#
+# Copyright (C) 2015 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+include $(call all-subdir-makefiles)
diff --git a/peripheralmanager/MODULE_LICENSE_APACHE2 b/peripheralmanager/MODULE_LICENSE_APACHE2
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/peripheralmanager/MODULE_LICENSE_APACHE2
diff --git a/peripheralmanager/NOTICE b/peripheralmanager/NOTICE
new file mode 100644
index 0000000..a849a94
--- /dev/null
+++ b/peripheralmanager/NOTICE
@@ -0,0 +1,190 @@
+
+   Copyright (c) 2014-2015, The Android Open Source Project
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
diff --git a/peripheralmanager/README b/peripheralmanager/README
new file mode 100644
index 0000000..00d0c95
--- /dev/null
+++ b/peripheralmanager/README
@@ -0,0 +1,3 @@
+PeripheralManager
+
+TODO(leecam): Write this file
diff --git a/peripheralmanager/client/Android.mk b/peripheralmanager/client/Android.mk
new file mode 100644
index 0000000..680becc
--- /dev/null
+++ b/peripheralmanager/client/Android.mk
@@ -0,0 +1,80 @@
+#
+# Copyright (C) 2015 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+LOCAL_PATH := $(call my-dir)
+
+libperipheralman_CommonCFlags := -Wall -Werror -Wno-unused-parameter
+libperipheralman_CommonCFlags += -Wno-sign-promo  # for libchrome
+libperipheralman_CommonCIncludes := \
+  $(LOCAL_PATH)/../common \
+  $(LOCAL_PATH)/../include \
+
+libperipheralman_CommonSharedLibraries := \
+  libbinder \
+  libbinderwrapper \
+  libbrillo \
+  libchrome \
+  libutils \
+
+# libperipheralman shared library
+# ========================================================
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := libperipheralman
+LOCAL_CPP_EXTENSION := .cc
+LOCAL_CFLAGS := $(libperipheralman_CommonCFlags)
+LOCAL_C_INCLUDES := $(libperipheralman_CommonCIncludes)
+LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/../include
+LOCAL_SHARED_LIBRARIES := $(libperipheralman_CommonSharedLibraries)
+LOCAL_STATIC_LIBRARIES := libperipheralman_binder
+LOCAL_SRC_FILES := \
+  gpio_impl.cc \
+  i2c_device_impl.cc \
+  led_impl.cc \
+  peripheral_manager_client_impl.cc \
+  spi_device_impl.cc \
+  uart_device_impl.cc \
+  wrapper.cc \
+
+include $(BUILD_SHARED_LIBRARY)
+
+# libperipheralman_tests executable
+# ========================================================
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := libperipheralman_tests
+LOCAL_CPP_EXTENSION := .cc
+LOCAL_CFLAGS := $(libperipheralman_CommonCFlags) -Wno-sign-compare
+LOCAL_C_INCLUDES := $(libperipheralman_CommonCIncludes)
+LOCAL_STATIC_LIBRARIES := libgtest libBionicGtestMain \
+  libperipheralman_binder \
+  libperipheralman_internal_test \
+  libgmock \
+
+LOCAL_SHARED_LIBRARIES := \
+  $(libperipheralman_CommonSharedLibraries) \
+  libperipheralman \
+  libbinderwrapper_test_support \
+
+LOCAL_SRC_FILES := \
+  gpio_unittest.cc \
+  i2c_unittest.cc \
+  led_unittest.cc \
+  peripheral_manager_client_unittest.cc \
+  spi_unittest.cc \
+  uart_unittest.cc \
+
+include $(BUILD_NATIVE_TEST)
diff --git a/peripheralmanager/client/gpio_impl.cc b/peripheralmanager/client/gpio_impl.cc
new file mode 100644
index 0000000..dfe5f83
--- /dev/null
+++ b/peripheralmanager/client/gpio_impl.cc
@@ -0,0 +1,118 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "gpio_impl.h"
+
+#include <android-base/unique_fd.h>
+#include <binder/Status.h>
+
+#include "peripheralmanager/constants.h"
+#include "peripheralmanager/gpio.h"
+
+using android::binder::Status;
+using android::os::IPeripheralManagerClient;
+using android::GpioActiveType;
+using android::GpioDirection;
+using android::GpioEdgeType;
+
+bool ActiveTypeFromInt(int type, GpioActiveType* out) {
+  if (type == ACTIVE_LOW) {
+    *out = android::kActiveLow;
+    return true;
+  } else if (type == ACTIVE_HIGH) {
+    *out = android::kActiveHigh;
+    return true;
+  }
+  return false;
+}
+
+bool DirectionFromInt(int direction, android::GpioDirection* out) {
+  switch (direction) {
+    case DIRECTION_IN:
+      *out = android::kDirectionIn;
+      return true;
+    case DIRECTION_OUT_INITIALLY_HIGH:
+      *out = android::kDirectionOutInitiallyHigh;
+      return true;
+    case DIRECTION_OUT_INITIALLY_LOW:
+      *out = android::kDirectionOutInitiallyLow;
+      return true;
+  }
+  return false;
+}
+
+bool EdgeTypeFromInt(int type, android::GpioEdgeType* out) {
+  switch (type) {
+    case NONE_EDGE:
+      *out = android::kEdgeNone;
+      return true;
+    case RISING_EDGE:
+      *out = android::kEdgeRising;
+      return true;
+    case FALLING_EDGE:
+      *out = android::kEdgeFalling;
+      return true;
+    case BOTH_EDGE:
+      *out = android::kEdgeBoth;
+      return true;
+  }
+  return false;
+}
+
+GpioImpl::GpioImpl(const std::string name,
+                   android::sp<IPeripheralManagerClient> client)
+    : name_(name), client_(client) {}
+
+GpioImpl::~GpioImpl() {
+  client_->ReleaseGpio(name_);
+}
+
+int GpioImpl::SetDirection(GpioDirection direction) {
+  return client_->SetGpioDirection(name_, direction).serviceSpecificErrorCode();
+}
+
+int GpioImpl::SetEdgeTriggerType(GpioEdgeType type) {
+  return client_->SetGpioEdge(name_, type).serviceSpecificErrorCode();
+}
+
+int GpioImpl::SetActiveType(GpioActiveType type) {
+  return client_->SetGpioActiveType(name_, type).serviceSpecificErrorCode();
+}
+
+int GpioImpl::SetValue(int value) {
+  return client_->SetGpioValue(name_, value != 0).serviceSpecificErrorCode();
+}
+
+int GpioImpl::GetValue(int* value) {
+  bool val = true;
+  Status ret = client_->GetGpioValue(name_, &val);
+  if (ret.isOk()) {
+    *value = val ? 1 : 0;
+  }
+  return ret.serviceSpecificErrorCode();
+}
+
+int GpioImpl::GetPollingFd(int* fd) {
+  android::base::unique_fd scoped_fd;
+  Status ret = client_->GetGpioPollingFd(name_, &scoped_fd);
+  if (ret.isOk()) {
+    uint8_t buf[2];
+    read(scoped_fd.get(), buf, 2);
+    lseek(scoped_fd.get(), 0, SEEK_SET);
+    *fd = scoped_fd.release();
+  }
+  return ret.serviceSpecificErrorCode();
+}
diff --git a/peripheralmanager/client/gpio_impl.h b/peripheralmanager/client/gpio_impl.h
new file mode 100644
index 0000000..089a4e3
--- /dev/null
+++ b/peripheralmanager/client/gpio_impl.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef SYSTEM_PERIPHERALMANAGER_GPIO_IMPL_H_
+#define SYSTEM_PERIPHERALMANAGER_GPIO_IMPL_H_
+
+#include <string>
+
+#include <android/os/IPeripheralManagerClient.h>
+#include <utils/StrongPointer.h>
+#include "peripheralmanager/constants.h"
+
+bool ActiveTypeFromInt(int type, android::GpioActiveType* out);
+bool DirectionFromInt(int direction, android::GpioDirection* out);
+bool EdgeTypeFromInt(int type, android::GpioEdgeType* out);
+
+class GpioImpl {
+ public:
+  GpioImpl(const std::string name,
+           android::sp<android::os::IPeripheralManagerClient> client);
+
+  ~GpioImpl();
+
+  int SetDirection(android::GpioDirection direction);
+
+  int SetEdgeTriggerType(android::GpioEdgeType type);
+
+  int SetActiveType(android::GpioActiveType type);
+
+  int SetValue(int value);
+
+  int GetValue(int* value);
+
+  int GetPollingFd(int* fd);
+
+ private:
+  std::string name_;
+  android::sp<android::os::IPeripheralManagerClient> client_;
+};
+
+#endif  // SYSTEM_PERIPHERALMANAGER_GPIO_IMPL_H_
diff --git a/peripheralmanager/client/gpio_unittest.cc b/peripheralmanager/client/gpio_unittest.cc
new file mode 100644
index 0000000..f5b54bc
--- /dev/null
+++ b/peripheralmanager/client/gpio_unittest.cc
@@ -0,0 +1,155 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <memory>
+
+#include <binderwrapper/binder_test_base.h>
+#include <binderwrapper/stub_binder_wrapper.h>
+#include <gtest/gtest.h>
+
+#include "gpio_driver_mock.h"
+#include "peripheral_manager.h"
+#include "peripheralmanager/gpio.h"
+#include "peripheralmanager/peripheral_manager_client.h"
+
+using android::GpioDriverInfo;
+using android::GpioDriverInfoBase;
+using android::GpioDriverMock;
+using android::GpioManager;
+using android::PeripheralManager;
+
+// Base class used to test the Gpio C API.
+// As we rely on static, global managers, we cannot run this tests in parallel.
+// Please use -j1 when running theses tests or you may see false negatives.
+class GpioTest : public android::BinderTestBase {
+ public:
+  void SetUp() {
+    android::sp<PeripheralManager> pman(new PeripheralManager);
+    android::String8 interface_desc(pman->getInterfaceDescriptor());
+    binder_wrapper()->SetBinderForService(interface_desc.string(), pman);
+
+    GpioManager* man = GpioManager::GetGpioManager();
+    man->RegisterDriver(std::unique_ptr<GpioDriverInfoBase>(
+        new GpioDriverInfo<GpioDriverMock, void*>(nullptr)));
+
+    man->RegisterGpioSysfs("IO1", 1);
+    man->RegisterGpioSysfs("IO2", 2);
+    man->RegisterGpioSysfs("IO3", 3);
+    man->RegisterGpioSysfs("IO4", 4);
+    man->RegisterGpioSysfs("IO5", 5);
+  }
+
+  void TearDown() { GpioManager::ResetGpioManager(); }
+};
+
+// Test that we list the Gpios available correctly.
+TEST_F(GpioTest, CanListGpios) {
+  BPeripheralManagerClient* client = BPeripheralManagerClient_new();
+  ASSERT_NE(nullptr, client);
+
+  int ngpios;
+  char** list = BPeripheralManagerClient_listGpio(client, &ngpios);
+
+  EXPECT_EQ(5, ngpios);
+  EXPECT_EQ("IO1", std::string(list[0]));
+  EXPECT_EQ("IO2", std::string(list[1]));
+  EXPECT_EQ("IO3", std::string(list[2]));
+  EXPECT_EQ("IO4", std::string(list[3]));
+  EXPECT_EQ("IO5", std::string(list[4]));
+
+  // Free the list.
+  for (int i = 0; i < 5; i++) {
+    free(list[i]);
+  }
+  free(list);
+}
+
+// Test that we can open a Gpio and act on it.
+TEST_F(GpioTest, CanOpenGpio) {
+  BPeripheralManagerClient* client = BPeripheralManagerClient_new();
+  ASSERT_NE(nullptr, client);
+
+  BGpio* gpio;
+  EXPECT_EQ(0, BPeripheralManagerClient_openGpio(client, "IO1", &gpio));
+  ASSERT_NE(nullptr, gpio);
+
+  // Can set the direction. If the direction is invalid, we fail.
+  EXPECT_EQ(0, BGpio_setDirection(gpio, DIRECTION_OUT_INITIALLY_HIGH));
+  EXPECT_EQ(EINVAL, BGpio_setDirection(gpio, 10));
+
+  // Can set the value.
+  EXPECT_EQ(0, BGpio_setValue(gpio, 1));
+
+  // Can set the active type. If the type is unknown, we fail.
+  EXPECT_EQ(0, BGpio_setActiveType(gpio, ACTIVE_LOW));
+  EXPECT_EQ(EINVAL, BGpio_setActiveType(gpio, 5));
+
+  EXPECT_EQ(0, BGpio_setDirection(gpio, DIRECTION_IN));
+
+  // Can read the value from the Gpio.
+  int value;
+  EXPECT_EQ(0, BGpio_getValue(gpio, &value));
+
+  // Setting the value returns an error.
+  EXPECT_EQ(EREMOTEIO, BGpio_setValue(gpio, 1));
+
+  // Can set the edge type. If the type is unknown, we fail.
+  EXPECT_EQ(0, BGpio_setEdgeTriggerType(gpio, RISING_EDGE));
+  EXPECT_EQ(EINVAL, BGpio_setEdgeTriggerType(gpio, -1));
+
+  BGpio_delete(gpio);
+  BPeripheralManagerClient_delete(client);
+}
+
+// Test that openning an unknown Gpio fails.
+TEST_F(GpioTest, OpenningUnknownGpioFails) {
+  BPeripheralManagerClient* client = BPeripheralManagerClient_new();
+  ASSERT_NE(nullptr, client);
+
+  BGpio* gpio = nullptr;
+  EXPECT_EQ(ENODEV,
+            BPeripheralManagerClient_openGpio(client, "unknown", &gpio));
+  EXPECT_EQ(nullptr, gpio);
+
+  BPeripheralManagerClient_delete(client);
+}
+
+// Test that we track ownership correctly (can't open a Gpio twice).
+TEST_F(GpioTest, GpioOnlyOpenedOnce) {
+  BPeripheralManagerClient* client = BPeripheralManagerClient_new();
+  ASSERT_NE(nullptr, client);
+
+  BGpio* gpio1;
+  BGpio* gpio2;
+  BGpio* gpio3;
+
+  EXPECT_EQ(0, BPeripheralManagerClient_openGpio(client, "IO1", &gpio1));
+  EXPECT_NE(nullptr, gpio1);
+
+  // Can't open the same Gpio.
+  EXPECT_EQ(EBUSY, BPeripheralManagerClient_openGpio(client, "IO1", &gpio2));
+
+  // Can open another Gpio.
+  EXPECT_EQ(0, BPeripheralManagerClient_openGpio(client, "IO3", &gpio3));
+
+  // Once we delete the struct, the Gpio is released and we can open it.
+  BGpio_delete(gpio1);
+  EXPECT_EQ(0, BPeripheralManagerClient_openGpio(client, "IO1", &gpio2));
+
+  BGpio_delete(gpio2);
+  BGpio_delete(gpio3);
+  BPeripheralManagerClient_delete(client);
+}
diff --git a/peripheralmanager/client/i2c_device_impl.cc b/peripheralmanager/client/i2c_device_impl.cc
new file mode 100644
index 0000000..01bef5c
--- /dev/null
+++ b/peripheralmanager/client/i2c_device_impl.cc
@@ -0,0 +1,106 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <vector>
+
+#include <peripheralmanager/i2c_device.h>
+
+#include "i2c_device_impl.h"
+
+using android::sp;
+using android::os::IPeripheralManagerClient;
+using android::binder::Status;
+
+I2cDeviceImpl::I2cDeviceImpl(const std::string& name,
+                             uint32_t address,
+                             sp<IPeripheralManagerClient> client)
+    : name_(name), address_(address), client_(client) {}
+
+I2cDeviceImpl::~I2cDeviceImpl() {
+  client_->ReleaseI2cDevice(name_, address_);
+}
+
+int I2cDeviceImpl::Read(void* data, uint32_t len, uint32_t* bytes_read) {
+  std::vector<uint8_t> read;
+  Status status = client_->I2cRead(
+      name_, address_, &read, len, reinterpret_cast<int32_t*>(bytes_read));
+  memcpy(data, read.data(), *bytes_read);
+  return status.serviceSpecificErrorCode();
+}
+
+int I2cDeviceImpl::ReadRegByte(uint8_t reg, uint8_t* val) {
+  int32_t tmp_val;
+  int ret = client_->I2cReadRegByte(name_, address_, reg, &tmp_val)
+                .serviceSpecificErrorCode();
+  if (!ret) {
+    *val = tmp_val;
+  }
+  return ret;
+}
+
+int I2cDeviceImpl::ReadRegWord(uint8_t reg, uint16_t* val) {
+  int32_t tmp_val;
+  int ret = client_->I2cReadRegWord(name_, address_, reg, &tmp_val)
+                .serviceSpecificErrorCode();
+  if (!ret) {
+    *val = tmp_val;
+  }
+  return ret;
+}
+
+int I2cDeviceImpl::ReadRegBuffer(uint8_t reg,
+                                 void* data,
+                                 uint32_t len,
+                                 uint32_t* bytes_read) {
+  std::vector<uint8_t> read(len);
+  Status status = client_->I2cReadRegBuffer(
+      name_, address_, reg, &read, len, reinterpret_cast<int32_t*>(bytes_read));
+  memcpy(data, read.data(), *bytes_read);
+
+  return status.serviceSpecificErrorCode();
+}
+
+int I2cDeviceImpl::Write(const void* data,
+                         uint32_t len,
+                         uint32_t* bytes_written) {
+  const uint8_t* bytes = reinterpret_cast<const uint8_t*>(data);
+  std::vector<uint8_t> v(bytes, bytes + len);
+  return client_
+      ->I2cWrite(name_, address_, v, reinterpret_cast<int32_t*>(bytes_written))
+      .serviceSpecificErrorCode();
+}
+
+int I2cDeviceImpl::WriteRegByte(uint8_t reg, uint8_t val) {
+  return client_->I2cWriteRegByte(name_, address_, reg, val)
+      .serviceSpecificErrorCode();
+}
+
+int I2cDeviceImpl::WriteRegWord(uint8_t reg, uint16_t val) {
+  return client_->I2cWriteRegWord(name_, address_, reg, val)
+      .serviceSpecificErrorCode();
+}
+
+int I2cDeviceImpl::WriteRegBuffer(uint8_t reg,
+                                  const void* data,
+                                  uint32_t len,
+                                  uint32_t* bytes_written) {
+  const uint8_t* bytes = reinterpret_cast<const uint8_t*>(data);
+  std::vector<uint8_t> v(bytes, bytes + len);
+  return client_
+      ->I2cWriteRegBuffer(
+          name_, address_, reg, v, reinterpret_cast<int32_t*>(bytes_written))
+      .serviceSpecificErrorCode();
+}
diff --git a/peripheralmanager/client/i2c_device_impl.h b/peripheralmanager/client/i2c_device_impl.h
new file mode 100644
index 0000000..412c662
--- /dev/null
+++ b/peripheralmanager/client/i2c_device_impl.h
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef SYSTEM_PERIPHERALMANAGER_I2C_DEVICE_IMPL_H_
+#define SYSTEM_PERIPHERALMANAGER_I2C_DEVICE_IMPL_H_
+
+#include <string>
+
+#include <android/os/IPeripheralManagerClient.h>
+#include <utils/StrongPointer.h>
+
+class I2cDeviceImpl {
+ public:
+  I2cDeviceImpl(const std::string& bus,
+                uint32_t address,
+                android::sp<android::os::IPeripheralManagerClient> client);
+
+  int Read(void* data, uint32_t len, uint32_t* bytes_read);
+  int ReadRegByte(uint8_t reg, uint8_t* val);
+  int ReadRegWord(uint8_t reg, uint16_t* val);
+  int ReadRegBuffer(uint8_t reg,
+                    void* data,
+                    uint32_t len,
+                    uint32_t* bytes_read);
+
+  int Write(const void* data, uint32_t len, uint32_t* bytes_written);
+  int WriteRegByte(uint8_t reg, uint8_t byte);
+  int WriteRegWord(uint8_t reg, uint16_t byte);
+  int WriteRegBuffer(uint8_t reg,
+                     const void* data,
+                     uint32_t len,
+                     uint32_t* bytes_written);
+
+  ~I2cDeviceImpl();
+
+ private:
+  std::string name_;
+  uint32_t address_;
+  android::sp<android::os::IPeripheralManagerClient> client_;
+};
+
+#endif  // SYSTEM_PERIPHERALMANAGER_I2C_DEVICE_IMPL_H_
diff --git a/peripheralmanager/client/i2c_unittest.cc b/peripheralmanager/client/i2c_unittest.cc
new file mode 100644
index 0000000..7e95a99
--- /dev/null
+++ b/peripheralmanager/client/i2c_unittest.cc
@@ -0,0 +1,190 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <memory>
+
+#include <binderwrapper/binder_test_base.h>
+#include <binderwrapper/stub_binder_wrapper.h>
+#include <gtest/gtest.h>
+
+#include "fake_i2c_devices.h"
+#include "i2c_driver_i2cdev.h"
+#include "peripheral_manager.h"
+#include "peripheralmanager/i2c_device.h"
+#include "peripheralmanager/peripheral_manager_client.h"
+
+using android::CharDeviceFactory;
+using android::FakeI2cDeviceFactory;
+using android::I2cDriverI2cDev;
+using android::I2cDriverInfo;
+using android::I2cDriverInfoBase;
+using android::I2cManager;
+using android::PeripheralManager;
+
+class I2cTest : public android::BinderTestBase {
+ public:
+  void SetUp() {
+    android::sp<PeripheralManager> pman(new PeripheralManager);
+    android::String8 interface_desc(pman->getInterfaceDescriptor());
+    binder_wrapper()->SetBinderForService(interface_desc.string(), pman);
+
+    I2cManager* man = I2cManager::GetI2cManager();
+    man->RegisterDriver(std::unique_ptr<I2cDriverInfoBase>(
+        new I2cDriverInfo<I2cDriverI2cDev, CharDeviceFactory*>(
+            &i2c_device_factory_)));
+
+    man->RegisterI2cDevBus("I2C0", 0);
+    man->RegisterI2cDevBus("I2C1", 1);
+  }
+
+  void TearDown() { I2cManager::ResetI2cManager(); }
+
+ private:
+  FakeI2cDeviceFactory i2c_device_factory_;
+};
+
+// Test that we can list the I2c buses correctly.
+TEST_F(I2cTest, ListI2cBuses) {
+  BPeripheralManagerClient* client = BPeripheralManagerClient_new();
+
+  int nbuses = -1;
+  char** devices = BPeripheralManagerClient_listI2cBuses(client, &nbuses);
+
+  ASSERT_EQ(2, nbuses);
+  EXPECT_EQ("I2C0", std::string(devices[0]));
+  EXPECT_EQ("I2C1", std::string(devices[1]));
+
+  for (int i = 0; i < nbuses; i++) {
+    free(devices[i]);
+  }
+  free(devices);
+
+  BPeripheralManagerClient_delete(client);
+}
+
+// Test that we can open a device and perform basic operations.
+TEST_F(I2cTest, OpenDevice) {
+  BPeripheralManagerClient* client = BPeripheralManagerClient_new();
+
+  BI2cDevice* device;
+  ASSERT_EQ(
+      0, BPeripheralManagerClient_openI2cDevice(client, "I2C0", 0x10, &device));
+
+  std::vector<uint8_t> buffer(40, 42);
+
+  uint32_t count = 0;
+
+  // Can write 20 bytes to the device.
+  EXPECT_EQ(0, BI2cDevice_write(device, buffer.data(), 20, &count));
+  EXPECT_EQ(20, count);
+
+  // Can write bytes and words to specific registers.
+  EXPECT_EQ(0, BI2cDevice_writeRegByte(device, 8, 60));
+  EXPECT_EQ(0, BI2cDevice_writeRegWord(device, 9, 2000));
+
+  // Can write 20 bytes to a specific register.
+  count = 0;
+  EXPECT_EQ(0,
+            BI2cDevice_writeRegBuffer(device, 10, buffer.data(), 20, &count));
+  EXPECT_EQ(20, count);
+
+  uint8_t byte;
+  uint16_t word;
+
+  // Can read 20 bytes from the device.
+  buffer.assign(40, 0);
+  count = 0;
+  EXPECT_EQ(0, BI2cDevice_read(device, buffer.data(), 20, &count));
+  EXPECT_EQ(20, count);
+
+  // Can read bytes and word from the device.
+  EXPECT_EQ(0, BI2cDevice_readRegByte(device, 8, &byte));
+  EXPECT_EQ(60, byte);
+
+  EXPECT_EQ(0, BI2cDevice_readRegWord(device, 9, &word));
+  EXPECT_EQ(2000, word);
+
+  // Can read 20 bytes from a specific register.
+  count = 0;
+  buffer.assign(40, 0);
+  EXPECT_EQ(0, BI2cDevice_readRegBuffer(device, 10, buffer.data(), 20, &count));
+  EXPECT_EQ(20, count);
+  for (int i = 0; i < 40; i++) {
+    EXPECT_EQ(i < 20 ? 42 : 0, buffer[i]);
+  }
+
+  BI2cDevice_delete(device);
+  BPeripheralManagerClient_delete(client);
+}
+
+// Test that we can't open the same device twice.
+TEST_F(I2cTest, CantOpenDeviceTwice) {
+  BPeripheralManagerClient* client = BPeripheralManagerClient_new();
+
+  BI2cDevice* device1 = nullptr;
+  BI2cDevice* device2 = nullptr;
+  BI2cDevice* device3 = nullptr;
+  BI2cDevice* device4 = nullptr;
+
+  // Can open the device once.
+  ASSERT_EQ(
+      0,
+      BPeripheralManagerClient_openI2cDevice(client, "I2C0", 0x10, &device1));
+  ASSERT_NE(nullptr, device1);
+
+  // Can open a device on the same address on a different bus.
+  ASSERT_EQ(
+      0,
+      BPeripheralManagerClient_openI2cDevice(client, "I2C1", 0x10, &device2));
+  ASSERT_NE(nullptr, device2);
+
+  // Can open another device on the same bus.
+  ASSERT_EQ(
+      0,
+      BPeripheralManagerClient_openI2cDevice(client, "I2C0", 0x13, &device3));
+  ASSERT_NE(nullptr, device3);
+
+  // Can't open a device already in use.
+  ASSERT_EQ(
+      EBUSY,
+      BPeripheralManagerClient_openI2cDevice(client, "I2C0", 0x10, &device4));
+  ASSERT_EQ(nullptr, device4);
+
+  // After releasing the device, we can re-open it.
+  BI2cDevice_delete(device1);
+  ASSERT_EQ(
+      0,
+      BPeripheralManagerClient_openI2cDevice(client, "I2C0", 0x10, &device4));
+  ASSERT_NE(nullptr, device4);
+
+  BI2cDevice_delete(device2);
+  BI2cDevice_delete(device3);
+  BI2cDevice_delete(device4);
+  BPeripheralManagerClient_delete(client);
+}
+
+// Test that we cleanly fail to open an unknown device.
+TEST_F(I2cTest, CantOpenUnknownDevice) {
+  BPeripheralManagerClient* client = BPeripheralManagerClient_new();
+
+  BI2cDevice* device = nullptr;
+  ASSERT_EQ(
+      ENODEV,
+      BPeripheralManagerClient_openI2cDevice(client, "I2C5", 0x10, &device));
+  ASSERT_EQ(nullptr, device);
+
+  BPeripheralManagerClient_delete(client);
+}
diff --git a/peripheralmanager/client/led_impl.cc b/peripheralmanager/client/led_impl.cc
new file mode 100644
index 0000000..164cf2b
--- /dev/null
+++ b/peripheralmanager/client/led_impl.cc
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <led_impl.h>
+
+using android::binder::Status;
+using android::os::IPeripheralManagerClient;
+using android::sp;
+
+LedImpl::LedImpl(const std::string& name, sp<IPeripheralManagerClient> client)
+    : name_(name), client_(client) {}
+
+LedImpl::~LedImpl() {
+  client_->ReleaseLed(name_);
+}
+
+int LedImpl::GetBrightness(uint32_t* brightness) {
+  int val;
+  Status status = client_->LedGetBrightness(name_, &val);
+  if (status.isOk())
+    *brightness = static_cast<uint32_t>(val);
+
+  return status.serviceSpecificErrorCode();
+}
+
+int LedImpl::GetMaxBrightness(uint32_t* max_brightness) {
+  int val;
+  Status status = client_->LedGetMaxBrightness(name_, &val);
+  if (status.isOk())
+    *max_brightness = static_cast<uint32_t>(val);
+
+  return status.serviceSpecificErrorCode();
+}
+
+int LedImpl::SetBrightness(uint32_t brightness) {
+  return client_->LedSetBrightness(name_, brightness)
+      .serviceSpecificErrorCode();
+}
diff --git a/peripheralmanager/client/led_impl.h b/peripheralmanager/client/led_impl.h
new file mode 100644
index 0000000..f848864
--- /dev/null
+++ b/peripheralmanager/client/led_impl.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef SYSTEM_PERIPHERALMANAGER_LED_IMPL_H_
+#define SYSTEM_PERIPHERALMANAGER_LED_IMPL_H_
+
+#include <string>
+
+#include <android/os/IPeripheralManagerClient.h>
+#include <utils/StrongPointer.h>
+
+class LedImpl {
+ public:
+  LedImpl(const std::string& name,
+          android::sp<android::os::IPeripheralManagerClient> client);
+  ~LedImpl();
+
+  int GetBrightness(uint32_t* brightness);
+  int GetMaxBrightness(uint32_t* max_brightness);
+  int SetBrightness(uint32_t brightness);
+
+ private:
+  std::string name_;
+  android::sp<android::os::IPeripheralManagerClient> client_;
+};
+
+#endif  // SYSTEM_PERIPHERALMANAGER_LED_IMPL_H_
diff --git a/peripheralmanager/client/led_unittest.cc b/peripheralmanager/client/led_unittest.cc
new file mode 100644
index 0000000..04c10d4
--- /dev/null
+++ b/peripheralmanager/client/led_unittest.cc
@@ -0,0 +1,162 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <memory>
+
+#include <base/files/file_util.h>
+#include <base/files/scoped_temp_dir.h>
+#include <binderwrapper/binder_test_base.h>
+#include <binderwrapper/stub_binder_wrapper.h>
+#include <gtest/gtest.h>
+
+#include "led_driver_sysfs.h"
+#include "led_manager.h"
+#include "peripheral_manager.h"
+#include "peripheralmanager/led.h"
+#include "peripheralmanager/peripheral_manager_client.h"
+
+using android::LedDriverInfo;
+using android::LedDriverInfoBase;
+using android::LedDriverSysfs;
+using android::LedManager;
+using android::PeripheralManager;
+
+class LedTest : public android::BinderTestBase {
+ public:
+  void SetUp() {
+    CHECK(dir_.CreateUniqueTempDir());
+
+    CreateLed("led1", 255, 0);
+    CreateLed("led2", 1000, 0);
+
+    led_path_prefix_ = dir_.path().value() + "/";
+
+    // Initialize the peripheral manager with the stub binder wrapper.
+    android::sp<PeripheralManager> pman(new PeripheralManager);
+    android::String8 interface_desc(pman->getInterfaceDescriptor());
+    binder_wrapper()->SetBinderForService(interface_desc.string(), pman);
+
+    LedManager* man = LedManager::GetLedManager();
+
+    // Register the testing version of the LED driver and the fake LEDs.
+    man->RegisterDriver(std::unique_ptr<LedDriverInfoBase>(
+        new LedDriverInfo<LedDriverSysfs, std::string*>(&led_path_prefix_)));
+
+    man->RegisterLedSysfs("LED1", "led1");
+    man->RegisterLedSysfs("LED2", "led2");
+  }
+
+  void CreateLed(const std::string& name, int max_brightness, int brightness) {
+    base::FilePath led(dir_.path().Append(name));
+    base::CreateDirectory(led);
+
+    std::string b_str = std::to_string(brightness);
+    std::string mb_str = std::to_string(max_brightness);
+
+    ASSERT_EQ(
+        b_str.size(),
+        base::WriteFile(led.Append("brightness"), b_str.c_str(), b_str.size()));
+    ASSERT_EQ(mb_str.size(),
+              base::WriteFile(
+                  led.Append("max_brightness"), mb_str.c_str(), mb_str.size()));
+  }
+
+  void TearDown() { LedManager::ResetLedManager(); }
+
+ private:
+  base::ScopedTempDir dir_;
+  std::string led_path_prefix_;
+};
+
+// Test that we can list the available LEDs.
+TEST_F(LedTest, CanListLeds) {
+  BPeripheralManagerClient* client = BPeripheralManagerClient_new();
+  ASSERT_NE(nullptr, client);
+
+  int nleds = -1;
+  char** leds = BPeripheralManagerClient_listLeds(client, &nleds);
+
+  EXPECT_EQ(2, nleds);
+  EXPECT_EQ("LED1", std::string(leds[0]));
+  EXPECT_EQ("LED2", std::string(leds[1]));
+
+  for (int i = 0; i < nleds; i++) {
+    free(leds[i]);
+  }
+  free(leds);
+
+  BPeripheralManagerClient_delete(client);
+}
+
+// Test that we can open an LED and act on it.
+TEST_F(LedTest, CanOpenLed) {
+  BPeripheralManagerClient* client = BPeripheralManagerClient_new();
+  ASSERT_NE(nullptr, client);
+
+  BLed* led;
+
+  ASSERT_EQ(0, BPeripheralManagerClient_openLed(client, "LED1", &led));
+
+  uint32_t max_brightness = 0;
+  EXPECT_EQ(0, BLed_getMaxBrightness(led, &max_brightness));
+  EXPECT_EQ(255, max_brightness);
+
+  uint32_t brightness = 0;
+  EXPECT_EQ(0, BLed_setBrightness(led, 10));
+  EXPECT_EQ(0, BLed_getBrightness(led, &brightness));
+  EXPECT_EQ(10, brightness);
+
+  BLed_delete(led);
+  BPeripheralManagerClient_delete(client);
+}
+
+// Test that we can't open an unexisting LED.
+TEST_F(LedTest, OpenningUnknownLed) {
+  BPeripheralManagerClient* client = BPeripheralManagerClient_new();
+  ASSERT_NE(nullptr, client);
+
+  BLed* led = nullptr;
+  EXPECT_EQ(ENODEV, BPeripheralManagerClient_openLed(client, "hello", &led));
+  EXPECT_EQ(nullptr, led);
+
+  BPeripheralManagerClient_delete(client);
+}
+
+// Test that we can't open an LED twice.
+TEST_F(LedTest, HandleConcurrentAccesses) {
+  BPeripheralManagerClient* client = BPeripheralManagerClient_new();
+  ASSERT_NE(nullptr, client);
+
+  // Can open LED1.
+  BLed* led1;
+  EXPECT_EQ(0, BPeripheralManagerClient_openLed(client, "LED1", &led1));
+
+  // Fails to open it twice.
+  BLed* led2;
+  EXPECT_EQ(EBUSY, BPeripheralManagerClient_openLed(client, "LED1", &led2));
+
+  // Can still open another LED.
+  BLed* led3;
+  EXPECT_EQ(0, BPeripheralManagerClient_openLed(client, "LED2", &led3));
+
+  // Once the LED is released, we can take ownership of it.
+  BLed_delete(led1);
+  EXPECT_EQ(0, BPeripheralManagerClient_openLed(client, "LED1", &led2));
+
+  BLed_delete(led2);
+  BLed_delete(led3);
+  BPeripheralManagerClient_delete(client);
+}
diff --git a/peripheralmanager/client/peripheral_manager_client_impl.cc b/peripheralmanager/client/peripheral_manager_client_impl.cc
new file mode 100644
index 0000000..4fdb731
--- /dev/null
+++ b/peripheralmanager/client/peripheral_manager_client_impl.cc
@@ -0,0 +1,102 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "peripheral_manager_client_impl.h"
+
+#include <android/os/IPeripheralManager.h>
+#include <binderwrapper/binder_wrapper.h>
+
+using android::binder::Status;
+
+bool PeripheralManagerClientImpl::Init() {
+  auto wrapper = android::interface_cast<android::os::IPeripheralManager>(
+      android::BinderWrapper::GetOrCreateInstance()->GetService(
+          "android.os.IPeripheralManager"));
+  lifeline_ = new android::BBinder;
+
+  return wrapper->GetClient(lifeline_, &client_).isOk();
+}
+
+int PeripheralManagerClientImpl::OpenGpio(const std::string& name,
+                                          std::unique_ptr<GpioImpl>* gpio) {
+  Status status = client_->OpenGpio(name);
+  if (status.isOk()) {
+    gpio->reset(new GpioImpl(name, client_));
+  }
+  return status.serviceSpecificErrorCode();
+}
+
+int PeripheralManagerClientImpl::ListGpio(std::vector<std::string>* gpios) {
+  Status status = client_->ListGpio(gpios);
+  return status.serviceSpecificErrorCode();
+}
+
+int PeripheralManagerClientImpl::OpenSpiDevice(
+    const std::string& name,
+    std::unique_ptr<SpiDeviceImpl>* device) {
+  Status status = client_->OpenSpiDevice(name);
+  if (status.isOk()) {
+    device->reset(new SpiDeviceImpl(name, client_));
+  }
+  return status.serviceSpecificErrorCode();
+}
+
+int PeripheralManagerClientImpl::ListSpiBuses(std::vector<std::string>* buses) {
+  Status status = client_->ListSpiBuses(buses);
+  return status.serviceSpecificErrorCode();
+}
+
+int PeripheralManagerClientImpl::ListLeds(std::vector<std::string>* leds) {
+  return client_->ListLeds(leds).serviceSpecificErrorCode();
+}
+
+int PeripheralManagerClientImpl::OpenLed(const std::string& name,
+                                         std::unique_ptr<LedImpl>* led) {
+  Status status = client_->OpenLed(name);
+  if (status.isOk()) {
+    led->reset(new LedImpl(name, client_));
+  }
+  return status.serviceSpecificErrorCode();
+}
+
+int PeripheralManagerClientImpl::OpenI2cDevice(
+    const std::string& name,
+    uint32_t address,
+    std::unique_ptr<I2cDeviceImpl>* device) {
+  Status status = client_->OpenI2cDevice(name, address);
+  if (status.isOk()) {
+    device->reset(new I2cDeviceImpl(name, address, client_));
+  }
+  return status.serviceSpecificErrorCode();
+}
+
+int PeripheralManagerClientImpl::ListI2cBuses(std::vector<std::string>* buses) {
+  return client_->ListI2cBuses(buses).serviceSpecificErrorCode();
+}
+
+int PeripheralManagerClientImpl::OpenUartDevice(
+    const std::string& name, std::unique_ptr<UartDeviceImpl>* device) {
+  Status status = client_->OpenUartDevice(name);
+  if (status.isOk()) {
+    device->reset(new UartDeviceImpl(name, client_));
+  }
+  return status.serviceSpecificErrorCode();
+}
+
+int PeripheralManagerClientImpl::ListUartDevices(
+    std::vector<std::string>* list) {
+  return client_->ListUartDevices(list).serviceSpecificErrorCode();
+}
diff --git a/peripheralmanager/client/peripheral_manager_client_impl.h b/peripheralmanager/client/peripheral_manager_client_impl.h
new file mode 100644
index 0000000..aba4739
--- /dev/null
+++ b/peripheralmanager/client/peripheral_manager_client_impl.h
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef SYSTEM_PERIPHERALMANAGER_PERIPHERAL_MANAGER_CLIENT_IMPL_H_
+#define SYSTEM_PERIPHERALMANAGER_PERIPHERAL_MANAGER_CLIENT_IMPL_H_
+
+#include <android/os/IPeripheralManagerClient.h>
+#include <utils/StrongPointer.h>
+
+#include "gpio_impl.h"
+#include "i2c_device_impl.h"
+#include "led_impl.h"
+#include "spi_device_impl.h"
+#include "uart_device_impl.h"
+
+class PeripheralManagerClientImpl {
+ public:
+  PeripheralManagerClientImpl() = default;
+
+  bool Init();
+
+  int OpenGpio(const std::string& name, std::unique_ptr<GpioImpl>* gpio);
+  int ListGpio(std::vector<std::string>* gpios);
+
+  int OpenSpiDevice(const std::string& name,
+                    std::unique_ptr<SpiDeviceImpl>* device);
+  int ListSpiBuses(std::vector<std::string>* buses);
+
+  int OpenLed(const std::string& name, std::unique_ptr<LedImpl>* device);
+  int ListLeds(std::vector<std::string>* leds);
+
+  int OpenI2cDevice(const std::string& name,
+                    uint32_t address,
+                    std::unique_ptr<I2cDeviceImpl>* device);
+  int ListI2cBuses(std::vector<std::string>* buses);
+
+  int OpenUartDevice(const std::string& name,
+                     std::unique_ptr<UartDeviceImpl>* device);
+  int ListUartDevices(std::vector<std::string>* buses);
+
+ private:
+  android::sp<android::os::IPeripheralManagerClient> client_;
+  android::sp<android::IBinder> lifeline_;
+};
+
+#endif  // SYSTEM_PERIPHERALMANAGER_PERIPHERAL_MANAGER_CLIENT_IMPL_H_
diff --git a/peripheralmanager/client/peripheral_manager_client_unittest.cc b/peripheralmanager/client/peripheral_manager_client_unittest.cc
new file mode 100644
index 0000000..e75af24
--- /dev/null
+++ b/peripheralmanager/client/peripheral_manager_client_unittest.cc
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <peripheralmanager/peripheral_manager_client.h>
+
+#include "gtest/gtest.h"
+
+namespace android {
+
+TEST(PeripheralManagerClient, Init) {
+}
+
+}  // namespace android
diff --git a/peripheralmanager/client/spi_device_impl.cc b/peripheralmanager/client/spi_device_impl.cc
new file mode 100644
index 0000000..d9bab6d
--- /dev/null
+++ b/peripheralmanager/client/spi_device_impl.cc
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <vector>
+
+#include <peripheralmanager/spi_device.h>
+
+#include "spi_device_impl.h"
+
+using android::sp;
+using android::os::IPeripheralManagerClient;
+using android::binder::Status;
+
+SpiDeviceImpl::SpiDeviceImpl(const std::string& name,
+                             sp<IPeripheralManagerClient> client)
+    : name_(name), client_(client) {}
+
+SpiDeviceImpl::~SpiDeviceImpl() {
+  client_->ReleaseSpiDevice(name_);
+}
+
+int SpiDeviceImpl::WriteByte(uint8_t byte) {
+  return client_->SpiDeviceWriteByte(name_, byte).serviceSpecificErrorCode();
+}
+
+int SpiDeviceImpl::WriteBuffer(const uint8_t* data, size_t len) {
+  std::vector<uint8_t> v(data, data + len);
+  return client_->SpiDeviceWriteBuffer(name_, v).serviceSpecificErrorCode();
+}
+
+int SpiDeviceImpl::Transfer(const uint8_t* tx_data,
+                            uint8_t* rx_data,
+                            size_t len) {
+  std::unique_ptr<std::vector<uint8_t>> sent;
+  std::unique_ptr<std::vector<uint8_t>> received;
+
+  if (tx_data == nullptr)
+    return EINVAL;
+
+  sent.reset(new std::vector<uint8_t>(tx_data, tx_data + len));
+
+  Status status = client_->SpiDeviceTransfer(name_, sent, &received, len);
+  if (status.isOk() && rx_data)
+    memcpy(rx_data, received->data(), len);
+  return status.serviceSpecificErrorCode();
+}
+
+int SpiDeviceImpl::SetFrequency(uint32_t freq_hz) {
+  return client_->SpiDeviceSetFrequency(name_, freq_hz)
+      .serviceSpecificErrorCode();
+}
+
+int SpiDeviceImpl::SetMode(int mode) {
+  return client_->SpiDeviceSetMode(name_, mode).serviceSpecificErrorCode();
+}
+
+int SpiDeviceImpl::SetBitJustification(int justification) {
+  return client_
+      ->SpiDeviceSetBitJustification(name_, justification == SPI_LSB_FIRST)
+      .serviceSpecificErrorCode();
+}
+
+int SpiDeviceImpl::SetBitsPerWord(uint32_t bits_per_word) {
+  return client_->SpiDeviceSetBitsPerWord(name_, bits_per_word)
+      .serviceSpecificErrorCode();
+}
+
+int SpiDeviceImpl::SetDelay(uint16_t delay_usecs) {
+  return client_->SpiDeviceSetDelay(name_, delay_usecs)
+      .serviceSpecificErrorCode();
+}
diff --git a/peripheralmanager/client/spi_device_impl.h b/peripheralmanager/client/spi_device_impl.h
new file mode 100644
index 0000000..ed076d5
--- /dev/null
+++ b/peripheralmanager/client/spi_device_impl.h
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef SYSTEM_PERIPHERALMANAGER_SPI_DEVICE_IMPL_H_
+#define SYSTEM_PERIPHERALMANAGER_SPI_DEVICE_IMPL_H_
+
+#include <string>
+
+#include <android/os/IPeripheralManagerClient.h>
+#include <utils/StrongPointer.h>
+
+class SpiDeviceImpl {
+ public:
+  SpiDeviceImpl(const std::string& bus,
+                android::sp<android::os::IPeripheralManagerClient> client);
+  ~SpiDeviceImpl();
+
+  int WriteByte(uint8_t byte);
+
+  int WriteBuffer(const uint8_t* data, size_t len);
+
+  int Transfer(const uint8_t* tx_data, uint8_t* rx_data, size_t len);
+
+  int SetFrequency(uint32_t speed_hz);
+
+  int SetMode(int mode);
+
+  int SetBitJustification(int bit_justification);
+
+  int SetBitsPerWord(uint32_t bits_per_word);
+
+  int SetDelay(uint16_t delay_usecs);
+
+ private:
+  std::string name_;
+  android::sp<android::os::IPeripheralManagerClient> client_;
+};
+
+#endif  // SYSTEM_PERIPHERALMANAGER_SPI_DEVICE_IMPL_H_
diff --git a/peripheralmanager/client/spi_unittest.cc b/peripheralmanager/client/spi_unittest.cc
new file mode 100644
index 0000000..cc8a3fb
--- /dev/null
+++ b/peripheralmanager/client/spi_unittest.cc
@@ -0,0 +1,200 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <memory>
+
+#include <binderwrapper/binder_test_base.h>
+#include <binderwrapper/stub_binder_wrapper.h>
+#include <gtest/gtest.h>
+
+#include "fake_devices.h"
+#include "peripheral_manager.h"
+#include "peripheralmanager/peripheral_manager_client.h"
+#include "peripheralmanager/spi_device.h"
+#include "spi_driver_spidev.h"
+
+using android::CharDeviceFactory;
+using android::FakeDeviceFactory;
+using android::SpiDriverInfo;
+using android::SpiDriverInfoBase;
+using android::SpiDriverSpiDev;
+using android::SpiManager;
+using android::PeripheralManager;
+
+// Base class used to test the Spi C API.
+// As we rely on static, global managers, we cannot run this tests in parallel.
+// Please use -j1 when running theses tests or you may see false negatives.
+class SpiTest : public android::BinderTestBase {
+ public:
+  void SetUp() {
+    android::sp<PeripheralManager> pman(new PeripheralManager);
+    android::String8 interface_desc(pman->getInterfaceDescriptor());
+    binder_wrapper()->SetBinderForService(interface_desc.string(), pman);
+
+    SpiManager* man = SpiManager::GetSpiManager();
+
+    man->GetSpiDevBuses();
+    man->RegisterDriver(std::unique_ptr<SpiDriverInfoBase>(
+        new SpiDriverInfo<SpiDriverSpiDev, CharDeviceFactory*>(
+            &device_factory_)));
+
+    man->RegisterSpiDevBus("SPI_A", 1, 0);
+    man->RegisterSpiDevBus("SPI_B", 1, 1);
+  }
+
+  void TearDown() { SpiManager::ResetSpiManager(); }
+
+ private:
+  FakeDeviceFactory device_factory_;
+};
+
+// Test that we can list the available devices.
+TEST_F(SpiTest, ListSpiDevices) {
+  BPeripheralManagerClient* client = BPeripheralManagerClient_new();
+
+  int ndev = -1;
+  char** devices = BPeripheralManagerClient_listSpiBuses(client, &ndev);
+
+  ASSERT_EQ(2, ndev);
+  EXPECT_EQ("SPI_A", std::string(devices[0]));
+  EXPECT_EQ("SPI_B", std::string(devices[1]));
+
+  for (int i = 0; i < ndev; i++) {
+    free(devices[i]);
+  }
+  free(devices);
+
+  BPeripheralManagerClient_delete(client);
+}
+
+// Test that we can open a device and use the basic functions.
+TEST_F(SpiTest, OpenSpiDevice) {
+  BPeripheralManagerClient* client = BPeripheralManagerClient_new();
+
+  BSpiDevice* device = nullptr;
+  ASSERT_EQ(0,
+            BPeripheralManagerClient_openSpiDevice(client, "SPI_A", &device));
+  ASSERT_NE(nullptr, device);
+
+  EXPECT_EQ(0, BSpiDevice_writeByte(device, 0x10));
+
+  std::vector<uint8_t> v = {1, 2, 3, 4};
+  EXPECT_EQ(0, BSpiDevice_writeBuffer(device, v.data(), v.size()));
+
+  BSpiDevice_delete(device);
+  BPeripheralManagerClient_delete(client);
+}
+
+// Test that the transfer function behave correctly.
+TEST_F(SpiTest, Transfer) {
+  BPeripheralManagerClient* client = BPeripheralManagerClient_new();
+
+  BSpiDevice* device = nullptr;
+  ASSERT_EQ(0,
+            BPeripheralManagerClient_openSpiDevice(client, "SPI_A", &device));
+  ASSERT_NE(nullptr, device);
+
+  // Passing an empty return pointer is valid.
+  std::vector<uint8_t> v = {0, 0, 0, 0};
+  uint8_t received[4];
+  EXPECT_EQ(0, BSpiDevice_transfer(device, v.data(), nullptr, v.size()));
+
+  // Passing an empty send pointer is invalid.
+  EXPECT_EQ(EINVAL, BSpiDevice_transfer(device, nullptr, &received, 4));
+
+  BSpiDevice_delete(device);
+  BPeripheralManagerClient_delete(client);
+}
+
+// Test that we can configure the device correctly and that we fail cleanly if
+// the configuration is incorrect.
+TEST_F(SpiTest, SetConfiguration) {
+  BPeripheralManagerClient* client = BPeripheralManagerClient_new();
+
+  BSpiDevice* device = nullptr;
+  ASSERT_EQ(0,
+            BPeripheralManagerClient_openSpiDevice(client, "SPI_A", &device));
+  ASSERT_NE(nullptr, device);
+
+  // We can set the mode and detect an invalid mode.
+  EXPECT_EQ(0, BSpiDevice_setMode(device, SPI_MODE0));
+  EXPECT_EQ(0, BSpiDevice_setMode(device, SPI_MODE1));
+  EXPECT_EQ(0, BSpiDevice_setMode(device, SPI_MODE2));
+  EXPECT_EQ(0, BSpiDevice_setMode(device, SPI_MODE3));
+  EXPECT_EQ(EINVAL, BSpiDevice_setMode(device, SPI_MODE3 + 1));
+
+  // We can set the bit justification and detect an invalid justification.
+  EXPECT_EQ(0, BSpiDevice_setBitJustification(device, SPI_LSB_FIRST));
+  EXPECT_EQ(0, BSpiDevice_setBitJustification(device, SPI_MSB_FIRST));
+  EXPECT_EQ(EINVAL, BSpiDevice_setBitJustification(device, SPI_MSB_FIRST + 1));
+
+  // We can set the frequency.
+  EXPECT_EQ(0, BSpiDevice_setFrequency(device, 100000));
+
+  // We can set the number of bits per word.
+  EXPECT_EQ(0, BSpiDevice_setBitsPerWord(device, 16));
+
+  // We can set the delay between transfers.
+  EXPECT_EQ(0, BSpiDevice_setDelay(device, 100));
+
+  BSpiDevice_delete(device);
+  BPeripheralManagerClient_delete(client);
+}
+
+// Test that we fail when trying to open the same device twice.
+TEST_F(SpiTest, CantOpenDeviceTwice) {
+  BPeripheralManagerClient* client = BPeripheralManagerClient_new();
+
+  BSpiDevice* device1 = nullptr;
+  BSpiDevice* device2 = nullptr;
+  BSpiDevice* device3 = nullptr;
+
+  // Can open SPI_A once.
+  ASSERT_EQ(0,
+            BPeripheralManagerClient_openSpiDevice(client, "SPI_A", &device1));
+  ASSERT_NE(nullptr, device1);
+
+  // The device can't be opened a second time because it is busy.
+  ASSERT_EQ(EBUSY,
+            BPeripheralManagerClient_openSpiDevice(client, "SPI_A", &device2));
+  ASSERT_EQ(nullptr, device2);
+
+  // Can open another device.
+  ASSERT_EQ(0,
+            BPeripheralManagerClient_openSpiDevice(client, "SPI_B", &device3));
+
+  // Once released, we can re-open the device.
+  BSpiDevice_delete(device1);
+  ASSERT_EQ(0,
+            BPeripheralManagerClient_openSpiDevice(client, "SPI_A", &device2));
+
+  BSpiDevice_delete(device2);
+  BSpiDevice_delete(device3);
+  BPeripheralManagerClient_delete(client);
+}
+
+// Test that we fail when trying to open an unknown device.
+TEST_F(SpiTest, CantOpenUnknownDevice) {
+  BPeripheralManagerClient* client = BPeripheralManagerClient_new();
+
+  BSpiDevice* device = nullptr;
+  ASSERT_EQ(
+      ENODEV,
+      BPeripheralManagerClient_openSpiDevice(client, "SPI_UNKOWN", &device));
+  ASSERT_EQ(nullptr, device);
+
+  BPeripheralManagerClient_delete(client);
+}
diff --git a/peripheralmanager/client/uart_device_impl.cc b/peripheralmanager/client/uart_device_impl.cc
new file mode 100644
index 0000000..becfd62
--- /dev/null
+++ b/peripheralmanager/client/uart_device_impl.cc
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "uart_device_impl.h"
+
+#include <binder/Status.h>
+
+using android::binder::Status;
+
+UartDeviceImpl::UartDeviceImpl(
+    const std::string& name,
+    android::sp<android::os::IPeripheralManagerClient> client)
+    : name_(name), client_(client) {}
+
+UartDeviceImpl::~UartDeviceImpl() {
+  client_->ReleaseUartDevice(name_);
+}
+
+int UartDeviceImpl::SetBaudrate(uint32_t baudrate) {
+  return client_->SetUartDeviceBaudrate(name_, baudrate)
+      .serviceSpecificErrorCode();
+}
+
+int UartDeviceImpl::Write(const void* data,
+                          uint32_t size,
+                          uint32_t* bytes_written) {
+  const uint8_t* d = reinterpret_cast<const uint8_t*>(data);
+  return client_
+      ->UartDeviceWrite(name_,
+                        std::vector<uint8_t>(d, d + size),
+                        reinterpret_cast<int32_t*>(bytes_written))
+      .serviceSpecificErrorCode();
+}
+
+int UartDeviceImpl::Read(void* data, uint32_t size, uint32_t* bytes_read) {
+  std::vector<uint8_t> v;
+  Status status = client_->UartDeviceRead(
+      name_, &v, size, reinterpret_cast<int32_t*>(bytes_read));
+  if (status.isOk()) {
+    memcpy(data, v.data(), *bytes_read);
+  }
+
+  return status.serviceSpecificErrorCode();
+}
diff --git a/peripheralmanager/client/uart_device_impl.h b/peripheralmanager/client/uart_device_impl.h
new file mode 100644
index 0000000..72d5d4a
--- /dev/null
+++ b/peripheralmanager/client/uart_device_impl.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef SYSTEM_PERIPHERALMANAGER_UART_DEVICE_IMPL_H_
+#define SYSTEM_PERIPHERALMANAGER_UART_DEVICE_IMPL_H_
+
+#include <string>
+
+#include <android/os/IPeripheralManagerClient.h>
+#include <utils/StrongPointer.h>
+
+class UartDeviceImpl {
+ public:
+  UartDeviceImpl(const std::string& name,
+                 android::sp<android::os::IPeripheralManagerClient> client);
+
+  ~UartDeviceImpl();
+
+  int SetBaudrate(uint32_t baudrate);
+
+  int Write(const void* data, uint32_t size, uint32_t* bytes_written);
+
+  int Read(void* data, uint32_t size, uint32_t* bytes_read);
+
+ private:
+  std::string name_;
+  android::sp<android::os::IPeripheralManagerClient> client_;
+};
+
+#endif  // SYSTEM_PERIPHERALMANAGER_UART_DEVICE_IMPL_H_
diff --git a/peripheralmanager/client/uart_unittest.cc b/peripheralmanager/client/uart_unittest.cc
new file mode 100644
index 0000000..ff46433
--- /dev/null
+++ b/peripheralmanager/client/uart_unittest.cc
@@ -0,0 +1,151 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <memory>
+
+#include <binderwrapper/binder_test_base.h>
+#include <binderwrapper/stub_binder_wrapper.h>
+#include <gtest/gtest.h>
+
+#include "fake_devices.h"
+#include "peripheral_manager.h"
+#include "peripheralmanager/peripheral_manager_client.h"
+#include "peripheralmanager/uart_device.h"
+#include "uart_driver_sysfs.h"
+
+using android::CharDeviceFactory;
+using android::FakeDeviceFactory;
+using android::UartDriverInfo;
+using android::UartDriverInfoBase;
+using android::UartDriverSysfs;
+using android::UartManager;
+using android::PeripheralManager;
+
+// Base class used to test the Uart C API.
+// As we rely on static, global managers, we cannot run this tests in parallel.
+// Please use -j1 when running theses tests or you may see false negatives.
+class UartTest : public android::BinderTestBase {
+ public:
+  void SetUp() {
+    android::sp<PeripheralManager> pman(new PeripheralManager);
+    android::String8 interface_desc(pman->getInterfaceDescriptor());
+    binder_wrapper()->SetBinderForService(interface_desc.string(), pman);
+
+    UartManager* man = UartManager::GetManager();
+
+    man->RegisterDriver(std::unique_ptr<UartDriverInfoBase>(
+        new UartDriverInfo<UartDriverSysfs, CharDeviceFactory*>(
+            &device_factory_)));
+
+    man->RegisterUartDevice("UART0", "/dev/ttyuart0");
+  }
+
+  void TearDown() { UartManager::ResetManager(); }
+
+ private:
+  FakeDeviceFactory device_factory_;
+};
+
+// Test that we can list the available devices.
+TEST_F(UartTest, ListDevices) {
+  BPeripheralManagerClient* client = BPeripheralManagerClient_new();
+
+  int n = 0;
+  char** list = BPeripheralManagerClient_listUartDevices(client, &n);
+
+  ASSERT_EQ(1, n);
+  ASSERT_EQ("UART0", std::string(list[0]));
+
+  free(list[0]);
+  free(list);
+
+  BPeripheralManagerClient_delete(client);
+}
+
+// Test that we can open a uart device and set the baudrate.
+TEST_F(UartTest, OpenDevice) {
+  BPeripheralManagerClient* client = BPeripheralManagerClient_new();
+
+  BUartDevice* device;
+  ASSERT_EQ(0,
+            BPeripheralManagerClient_openUartDevice(client, "UART0", &device));
+
+  // Can set a valid baudrate.
+  ASSERT_EQ(0, BUartDevice_setBaudrate(device, 115200));
+
+  // Setting an invalid baudrate should return an error.
+  ASSERT_EQ(EINVAL, BUartDevice_setBaudrate(device, 12345));
+
+  BUartDevice_delete(device);
+  BPeripheralManagerClient_delete(client);
+}
+
+// Test that we can detect when a device is accessed twice and report an
+// appropriate error.
+TEST_F(UartTest, HandlesConflict) {
+  BPeripheralManagerClient* client = BPeripheralManagerClient_new();
+
+  BUartDevice* device_a;
+  BUartDevice* device_b;
+
+  // Can open UART0 once.
+  ASSERT_EQ(
+      0, BPeripheralManagerClient_openUartDevice(client, "UART0", &device_a));
+
+  // Can't open it twice.
+  ASSERT_EQ(
+      EBUSY,
+      BPeripheralManagerClient_openUartDevice(client, "UART0", &device_b));
+
+  // Can open it again once closed.
+  BUartDevice_delete(device_a);
+  ASSERT_EQ(
+      0, BPeripheralManagerClient_openUartDevice(client, "UART0", &device_b));
+
+  BUartDevice_delete(device_b);
+  BPeripheralManagerClient_delete(client);
+}
+
+// Test that we report the right error when trying to open an unknown device.
+TEST_F(UartTest, UnknownDevice) {
+  BPeripheralManagerClient* client = BPeripheralManagerClient_new();
+
+  BUartDevice* device;
+  ASSERT_EQ(
+      ENODEV,
+      BPeripheralManagerClient_openUartDevice(client, "unknown", &device));
+
+  BPeripheralManagerClient_delete(client);
+}
+
+// Test that we can read and write to a device.
+TEST_F(UartTest, ReadWrite) {
+  BPeripheralManagerClient* client = BPeripheralManagerClient_new();
+
+  BUartDevice* device;
+  ASSERT_EQ(0,
+            BPeripheralManagerClient_openUartDevice(client, "UART0", &device));
+
+  char buf[40];
+  uint32_t nwritten;
+  EXPECT_EQ(0, BUartDevice_write(device, buf, 40, &nwritten));
+
+  uint32_t nread;
+  EXPECT_EQ(0, BUartDevice_read(device, buf, 40, &nread));
+
+  BUartDevice_delete(device);
+  BPeripheralManagerClient_delete(client);
+}
diff --git a/peripheralmanager/client/wrapper.cc b/peripheralmanager/client/wrapper.cc
new file mode 100644
index 0000000..f9cc3dc
--- /dev/null
+++ b/peripheralmanager/client/wrapper.cc
@@ -0,0 +1,383 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <utils/StrongPointer.h>
+#include <memory>
+
+#include "gpio_impl.h"
+#include "led_impl.h"
+#include "peripheral_manager_client_impl.h"
+#include "peripheralmanager/peripheral_manager_client.h"
+#include "spi_device_impl.h"
+#include "uart_device_impl.h"
+
+namespace {
+
+// This is horrible. Get rid of it!!!
+static char** ConvertStringVectorToC(const std::vector<std::string>& strings) {
+  char** c_strings = (char**)malloc(strings.size() * sizeof(*c_strings));
+  for (size_t i = 0; i < strings.size(); i++) {
+    c_strings[i] = (char*)malloc(strings[i].size() + 1);
+    memset(c_strings[i], 0, strings[i].size() + 1);
+    strcpy(c_strings[i], strings[i].c_str());
+  }
+  return c_strings;
+}
+
+}  // namespace
+
+struct BPeripheralManagerClient {
+  PeripheralManagerClientImpl* impl;
+};
+
+struct BGpio {
+  GpioImpl* impl;
+};
+
+struct BSpiDevice {
+  SpiDeviceImpl* impl;
+};
+
+struct BLed {
+  LedImpl* impl;
+};
+
+struct BI2cDevice {
+  I2cDeviceImpl* impl;
+};
+
+struct BUartDevice {
+  UartDeviceImpl* impl;
+};
+
+BPeripheralManagerClient* BPeripheralManagerClient_new() {
+  std::unique_ptr<PeripheralManagerClientImpl> impl(
+      new PeripheralManagerClientImpl);
+  if (impl->Init()) {
+    return new BPeripheralManagerClient{impl.release()};
+  }
+
+  return NULL;
+}
+
+void BPeripheralManagerClient_delete(BPeripheralManagerClient* client) {
+  delete client->impl;
+  delete client;
+}
+
+// GPIO API
+char** BPeripheralManagerClient_listGpio(const BPeripheralManagerClient* client,
+                                         int* num_gpio) {
+  std::vector<std::string> gpios;
+  client->impl->ListGpio(&gpios);
+  *num_gpio = gpios.size();
+  return ConvertStringVectorToC(gpios);
+}
+
+int BPeripheralManagerClient_openGpio(const BPeripheralManagerClient* client,
+                                      const char* name,
+                                      BGpio** gpio) {
+  std::unique_ptr<GpioImpl> tmp;
+  int ret = client->impl->OpenGpio(name, &tmp);
+  if (!ret) {
+    *gpio = new BGpio{tmp.release()};
+  }
+  return ret;
+}
+
+int BGpio_setDirection(const BGpio* gpio, int direction) {
+  android::GpioDirection dir;
+  if (!DirectionFromInt(direction, &dir))
+    return EINVAL;
+
+  return gpio->impl->SetDirection(dir);
+}
+
+int BGpio_setEdgeTriggerType(const BGpio* gpio, int type) {
+  android::GpioEdgeType t;
+  if (!EdgeTypeFromInt(type, &t))
+    return EINVAL;
+
+  return gpio->impl->SetEdgeTriggerType(t);
+}
+
+int BGpio_setActiveType(const BGpio* gpio, int type) {
+  android::GpioActiveType t;
+  if (!ActiveTypeFromInt(type, &t))
+    return EINVAL;
+
+  return gpio->impl->SetActiveType(t);
+}
+
+int BGpio_setValue(const BGpio* gpio, int value) {
+  return gpio->impl->SetValue(value);
+}
+
+int BGpio_getValue(const BGpio* gpio, int* value) {
+  return gpio->impl->GetValue(value);
+}
+
+int BGpio_getPollingFd(const BGpio* gpio, int* fd) {
+  return gpio->impl->GetPollingFd(fd);
+}
+
+int BGpio_ackInterruptEvent(int fd) {
+  uint8_t buf[2];
+  lseek(fd, 0, SEEK_SET);
+  read(fd, buf, 2);
+  return 0;
+}
+
+void BGpio_delete(BGpio* gpio) {
+  delete gpio->impl;
+  delete gpio;
+}
+
+// SPI API
+char** BPeripheralManagerClient_listSpiBuses(
+    const BPeripheralManagerClient* client,
+    int* num_spi_buses) {
+  std::vector<std::string> list;
+  client->impl->ListSpiBuses(&list);
+  *num_spi_buses = list.size();
+  return ConvertStringVectorToC(list);
+}
+
+int BPeripheralManagerClient_openSpiDevice(
+    const BPeripheralManagerClient* client,
+    const char* name,
+    BSpiDevice** dev) {
+  std::unique_ptr<SpiDeviceImpl> impl;
+  int ret = client->impl->OpenSpiDevice(name, &impl);
+  if (impl) {
+    *dev = new BSpiDevice{impl.release()};
+  }
+
+  return ret;
+}
+
+int BSpiDevice_writeByte(const BSpiDevice* device, uint8_t val) {
+  return device->impl->WriteByte(val);
+}
+
+int BSpiDevice_writeBuffer(const BSpiDevice* device,
+                           const void* data,
+                           size_t len) {
+  return device->impl->WriteBuffer(static_cast<const uint8_t*>(data), len);
+}
+
+int BSpiDevice_transfer(const BSpiDevice* device,
+                        const void* tx_data,
+                        void* rx_data,
+                        size_t len) {
+  return device->impl->Transfer(static_cast<const uint8_t*>(tx_data),
+                                static_cast<uint8_t*>(rx_data), len);
+}
+
+int BSpiDevice_setFrequency(const BSpiDevice* device, uint32_t freq_hz) {
+  return device->impl->SetFrequency(freq_hz);
+}
+
+int BSpiDevice_setMode(const BSpiDevice* device, int mode) {
+  if (mode == SPI_MODE0 || mode == SPI_MODE1 || mode == SPI_MODE2 ||
+      mode == SPI_MODE3) {
+    return device->impl->SetMode(mode);
+  }
+  return EINVAL;
+}
+
+int BSpiDevice_setBitJustification(const BSpiDevice* device,
+                                   int bit_justification) {
+  if (bit_justification == SPI_LSB_FIRST ||
+      bit_justification == SPI_MSB_FIRST) {
+    return device->impl->SetBitJustification(bit_justification);
+  }
+  return EINVAL;
+}
+
+int BSpiDevice_setBitsPerWord(const BSpiDevice* device, uint8_t bits_per_word) {
+  return device->impl->SetBitsPerWord(bits_per_word);
+}
+
+int BSpiDevice_setDelay(const BSpiDevice* device, uint16_t delay_usecs) {
+  return device->impl->SetDelay(delay_usecs);
+}
+
+void BSpiDevice_delete(BSpiDevice* device) {
+  delete device->impl;
+  delete device;
+}
+
+char** BPeripheralManagerClient_listLeds(const BPeripheralManagerClient* client,
+                                         int* num_leds) {
+  std::vector<std::string> list;
+  client->impl->ListLeds(&list);
+  *num_leds = list.size();
+  return ConvertStringVectorToC(list);
+}
+
+int BPeripheralManagerClient_openLed(const BPeripheralManagerClient* client,
+                                     const char* name,
+                                     BLed** led) {
+  std::unique_ptr<LedImpl> impl;
+  int ret = client->impl->OpenLed(name, &impl);
+  if (!ret)
+    *led = new BLed{impl.release()};
+
+  return ret;
+}
+
+int BLed_setBrightness(const BLed* led, uint32_t brightness) {
+  return led->impl->SetBrightness(brightness);
+}
+
+int BLed_getBrightness(const BLed* led, uint32_t* brightness) {
+  return led->impl->GetBrightness(brightness);
+}
+
+int BLed_getMaxBrightness(const BLed* led, uint32_t* max_brightness) {
+  return led->impl->GetMaxBrightness(max_brightness);
+}
+
+void BLed_delete(BLed* led) {
+  delete led->impl;
+  delete led;
+}
+
+// I2C API
+char** BPeripheralManagerClient_listI2cBuses(
+    const BPeripheralManagerClient* client, int* num_i2c_buses) {
+  std::vector<std::string> list;
+  client->impl->ListI2cBuses(&list);
+  *num_i2c_buses = list.size();
+  return ConvertStringVectorToC(list);
+}
+
+int BPeripheralManagerClient_openI2cDevice(
+    const BPeripheralManagerClient* client,
+    const char* name,
+    uint32_t address,
+    BI2cDevice** dev) {
+  std::unique_ptr<I2cDeviceImpl> impl;
+  int ret = client->impl->OpenI2cDevice(name, address, &impl);
+  if (ret == 0) {
+    *dev = new BI2cDevice{impl.release()};
+  }
+
+  return ret;
+}
+
+int BI2cDevice_read(const BI2cDevice* device,
+                    void* data,
+                    uint32_t len,
+                    uint32_t* bytes_read) {
+  return device->impl->Read(data, len, bytes_read);
+}
+
+int BI2cDevice_readRegByte(const BI2cDevice* device,
+                           uint8_t reg,
+                           uint8_t* val) {
+  return device->impl->ReadRegByte(reg, val);
+}
+
+int BI2cDevice_readRegWord(const BI2cDevice* device,
+                           uint8_t reg,
+                           uint16_t* val) {
+  return device->impl->ReadRegWord(reg, val);
+}
+
+int BI2cDevice_readRegBuffer(const BI2cDevice* device,
+                             uint8_t reg,
+                             void* data,
+                             uint32_t len,
+                             uint32_t* bytes_read) {
+  return device->impl->ReadRegBuffer(reg, data, len, bytes_read);
+}
+
+int BI2cDevice_write(const BI2cDevice* device,
+                     const void* data,
+                     uint32_t len,
+                     uint32_t* bytes_written) {
+  return device->impl->Write(data, len, bytes_written);
+}
+
+int BI2cDevice_writeRegByte(const BI2cDevice* device,
+                            uint8_t reg,
+                            uint8_t val) {
+  return device->impl->WriteRegByte(reg, val);
+}
+
+int BI2cDevice_writeRegWord(const BI2cDevice* device,
+                            uint8_t reg,
+                            uint16_t val) {
+  return device->impl->WriteRegWord(reg, val);
+}
+
+int BI2cDevice_writeRegBuffer(const BI2cDevice* device,
+                              uint8_t reg,
+                              const void* data,
+                              uint32_t len,
+                              uint32_t* bytes_written) {
+  return device->impl->WriteRegBuffer(reg, data, len, bytes_written);
+}
+
+void BI2cDevice_delete(BI2cDevice* device) {
+  delete device->impl;
+  delete device;
+}
+
+char** BPeripheralManagerClient_listUartDevices(
+    const BPeripheralManagerClient* client, int* num_uart_devices) {
+  std::vector<std::string> list;
+  client->impl->ListUartDevices(&list);
+  *num_uart_devices = list.size();
+  return ConvertStringVectorToC(list);
+}
+
+int BPeripheralManagerClient_openUartDevice(
+    const BPeripheralManagerClient* client,
+    const char* name,
+    BUartDevice** device) {
+  std::unique_ptr<UartDeviceImpl> impl;
+  int ret = client->impl->OpenUartDevice(name, &impl);
+  if (ret == 0) {
+    *device = new BUartDevice{impl.release()};
+  }
+  return ret;
+}
+
+int BUartDevice_setBaudrate(const BUartDevice* device, uint32_t baudrate) {
+  return device->impl->SetBaudrate(baudrate);
+}
+
+int BUartDevice_write(const BUartDevice* device,
+                      const void* data,
+                      uint32_t size,
+                      uint32_t* bytes_written) {
+  return device->impl->Write(data, size, bytes_written);
+}
+
+int BUartDevice_read(const BUartDevice* device,
+                     void* data,
+                     uint32_t size,
+                     uint32_t* bytes_read) {
+  return device->impl->Read(data, size, bytes_read);
+}
+
+void BUartDevice_delete(BUartDevice* device) {
+  delete device->impl;
+  delete device;
+}
diff --git a/peripheralmanager/common/peripheralmanager/constants.h b/peripheralmanager/common/peripheralmanager/constants.h
new file mode 100644
index 0000000..d30a28f
--- /dev/null
+++ b/peripheralmanager/common/peripheralmanager/constants.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef SYSTEM_PERIPHERALMANAGER_PERIPHERALMANAGER_CONSTANTS_H_
+#define SYSTEM_PERIPHERALMANAGER_PERIPHERALMANAGER_CONSTANTS_H_
+
+namespace android {
+
+enum GpioEdgeType {
+  kEdgeNone,
+  kEdgeRising,
+  kEdgeFalling,
+  kEdgeBoth,
+};
+
+enum GpioDirection {
+  kDirectionIn,
+  kDirectionOutInitiallyHigh,
+  kDirectionOutInitiallyLow,
+};
+
+enum GpioActiveType {
+  kActiveLow,
+  kActiveHigh,
+};
+
+// The SPI modes are the same as the ones defined by the linux kernel.
+enum SpiMode {
+  kMode0,
+  kMode1,
+  kMode2,
+  kMode3,
+};
+
+}  // namespace android
+
+#endif  // SYSTEM_PERIPHERALMANAGER_PERIPHERALMANAGER_CONSTANTS_H_
diff --git a/peripheralmanager/daemon/Android.mk b/peripheralmanager/daemon/Android.mk
new file mode 100644
index 0000000..935ee62
--- /dev/null
+++ b/peripheralmanager/daemon/Android.mk
@@ -0,0 +1,141 @@
+#
+# Copyright (C) 2015 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+LOCAL_PATH := $(call my-dir)
+
+peripheralman_CommonCFlags := -Wall -Werror -Wno-unused-parameter
+peripheralman_CommonCFlags += -Wno-sign-promo  # for libchrome
+peripheralman_CommonCIncludes := \
+  $(LOCAL_PATH)/../common \
+  $(LOCAL_PATH)/../include \
+  external/gtest/include \
+
+peripheralman_CommonSharedLibraries := \
+  libbinder \
+  libbinderwrapper \
+  libchrome \
+  libutils \
+  libhardware \
+
+libperipheralman_internal_CommonSources := \
+  char_device.cc \
+  gpio_driver_sysfs.cc \
+  gpio_manager.cc \
+  i2c_driver_i2cdev.cc \
+  i2c_manager.cc \
+  led_driver_sysfs.cc \
+  led_manager.cc \
+  peripheral_manager.cc \
+  peripheral_manager_client.cc \
+  pin_mux_manager.cc \
+  spi_driver_spidev.cc \
+  spi_manager.cc \
+  uart_driver_sysfs.cc \
+  uart_manager.cc \
+
+# peripheralman executable
+# ========================================================
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := peripheralman
+LOCAL_REQUIRED_MODULES := peripheralman.rc
+LOCAL_CPP_EXTENSION := .cc
+LOCAL_CFLAGS := $(peripheralman_CommonCFlags)
+LOCAL_C_INCLUDES := $(peripheralman_CommonCIncludes)
+
+LOCAL_STATIC_LIBRARIES := \
+  libperipheralman_internal \
+  libperipheralman_binder \
+  peripheral_manager_hal_headers \
+
+LOCAL_SHARED_LIBRARIES := \
+  $(peripheralman_CommonSharedLibraries) \
+  libbrillo \
+  libbrillo-binder \
+
+LOCAL_SRC_FILES := main.cc
+LOCAL_INIT_RC := peripheralman.rc
+include $(BUILD_EXECUTABLE)
+
+# libperipheralman_internal static lib
+# ========================================================
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := libperipheralman_internal
+LOCAL_CPP_EXTENSION := .cc
+LOCAL_CFLAGS := $(peripheralman_CommonCFlags)
+LOCAL_C_INCLUDES := $(peripheralman_CommonCIncludes)
+LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/../include
+LOCAL_STATIC_LIBRARIES := \
+  libperipheralman_binder \
+  peripheral_manager_hal_headers \
+
+LOCAL_SHARED_LIBRARIES := \
+  $(peripheralman_CommonSharedLibraries) \
+
+LOCAL_SRC_FILES := $(libperipheralman_internal_CommonSources)
+include $(BUILD_STATIC_LIBRARY)
+
+# libperipheral_internal_test static lib used to test the client.
+# ===============================================================
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := libperipheralman_internal_test
+LOCAL_CPP_EXTENSION := .cc
+LOCAL_CFLAGS := $(peripheralman_CommonCFlags)
+LOCAL_C_INCLUDES := $(peripheralman_CommonCIncludes)
+LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/../include \
+  $(LOCAL_PATH) \
+  $(LOCAL_PATH)/../hal \
+
+LOCAL_STATIC_LIBRARIES := \
+  libperipheralman_binder \
+  peripheral_manager_hal_headers \
+
+LOCAL_SHARED_LIBRARIES := \
+  libbinder \
+  libbinderwrapper_test_support \
+  libchrome \
+  libutils \
+  libhardware \
+
+LOCAL_SRC_FILES := $(libperipheralman_internal_CommonSources) \
+  fake_devices.cc \
+  fake_i2c_devices.cc \
+
+include $(BUILD_STATIC_LIBRARY)
+
+# peripheralman unit tests
+# ========================================================
+include $(CLEAR_VARS)
+LOCAL_MODULE := peripheralman_unittests
+LOCAL_CPP_EXTENSION := .cc
+LOCAL_CFLAGS := $(peripheralman_CommonCFlags)
+LOCAL_C_INCLUDES := $(peripheralman_CommonCIncludes)
+LOCAL_STATIC_LIBRARIES := libperipheralman_internal \
+  peripheral_manager_hal_headers \
+
+LOCAL_SHARED_LIBRARIES := \
+  libchrome \
+
+LOCAL_SRC_FILES := \
+  fake_devices.cc \
+  fake_i2c_devices.cc \
+  gpio_manager_unittest.cc \
+  pin_mux_manager_unittest.cc \
+  spi_manager_unittest.cc \
+
+include $(BUILD_NATIVE_TEST)
diff --git a/peripheralmanager/daemon/char_device.cc b/peripheralmanager/daemon/char_device.cc
new file mode 100644
index 0000000..720c439
--- /dev/null
+++ b/peripheralmanager/daemon/char_device.cc
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "char_device.h"
+
+#include <fcntl.h>
+#include <poll.h>
+#include <sys/ioctl.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+namespace android {
+
+CharDevice::CharDevice() {}
+CharDevice::~CharDevice() {}
+
+int CharDevice::Open(const char* pathname, int flags) {
+  return open(pathname, flags);
+}
+
+int CharDevice::Close(int fd) {
+  return close(fd);
+}
+
+int CharDevice::Ioctl(int fd, int request, void* argp) {
+  return ioctl(fd, request, argp);
+}
+
+ssize_t CharDevice::Read(int fd, void* buf, size_t count) {
+  return read(fd, buf, count);
+}
+
+ssize_t CharDevice::Write(int fd, const void* buf, size_t count) {
+  return write(fd, buf, count);
+}
+
+int CharDevice::Poll(struct pollfd* fds, nfds_t nfds, int timeout) {
+  return poll(fds, nfds, timeout);
+}
+
+}  // namespace android
diff --git a/peripheralmanager/daemon/char_device.h b/peripheralmanager/daemon/char_device.h
new file mode 100644
index 0000000..53e6a3e
--- /dev/null
+++ b/peripheralmanager/daemon/char_device.h
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef SYSTEM_PERIPHERALMANAGER_DAEMON_CHAR_DEVICE_H_
+#define SYSTEM_PERIPHERALMANAGER_DAEMON_CHAR_DEVICE_H_
+
+#include <poll.h>
+#include <stdlib.h>
+
+#include <memory>
+
+namespace android {
+
+// Used to wrap the interface to a char device file.
+// This can then be stubbed out and used in unittests.
+class CharDeviceInterface {
+ public:
+  CharDeviceInterface(){};
+  virtual ~CharDeviceInterface(){};
+
+  virtual int Open(const char* pathname, int flags) = 0;
+  virtual int Close(int fd) = 0;
+  virtual int Ioctl(int fd, int request, void* argp) = 0;
+  virtual ssize_t Read(int fd, void* buf, size_t count) = 0;
+  virtual ssize_t Write(int fd, const void* buf, size_t count) = 0;
+  virtual int Poll(struct pollfd* fds, nfds_t nfds, int timeout) = 0;
+};
+
+class CharDevice : public CharDeviceInterface {
+ public:
+  CharDevice();
+  ~CharDevice() override;
+
+  int Open(const char* pathname, int flags) override;
+  int Close(int fd) override;
+  int Ioctl(int fd, int request, void* argp) override;
+  ssize_t Read(int fd, void* buf, size_t count) override;
+  ssize_t Write(int fd, const void* buf, size_t count) override;
+  int Poll(struct pollfd* fds, nfds_t nfds, int timeout) override;
+};
+
+class CharDeviceFactory {
+ public:
+  CharDeviceFactory() {}
+  virtual ~CharDeviceFactory() {}
+
+  virtual std::unique_ptr<CharDeviceInterface> NewCharDevice() = 0;
+};
+
+}  // namespace android
+
+#endif  // SYSTEM_PERIPHERALMANAGER_DAEMON_CHAR_DEVICE_H_
\ No newline at end of file
diff --git a/peripheralmanager/daemon/fake_devices.cc b/peripheralmanager/daemon/fake_devices.cc
new file mode 100644
index 0000000..2555a95
--- /dev/null
+++ b/peripheralmanager/daemon/fake_devices.cc
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "fake_devices.h"
+
+#include <stdio.h>
+
+namespace android {
+
+FakeCharDevice::FakeCharDevice() {}
+FakeCharDevice::~FakeCharDevice() {}
+
+// TODO(leecam): Implement these.
+int FakeCharDevice::Open(const char* pathname, int flags) {
+  return 1;
+}
+
+int FakeCharDevice::Close(int fd) {
+  return 0;
+}
+
+int FakeCharDevice::Ioctl(int fd, int request, void* argp) {
+  return 0;
+}
+
+ssize_t FakeCharDevice::Read(int fd, void* buf, size_t count) {
+  return count;
+}
+
+ssize_t FakeCharDevice::Write(int fd, const void* buf, size_t count) {
+  return count;
+}
+
+int FakeCharDevice::Poll(struct pollfd* fds, nfds_t nfds, int timeout) {
+  return 0;
+}
+
+FakeDeviceFactory::FakeDeviceFactory() {}
+
+FakeDeviceFactory::~FakeDeviceFactory() {}
+
+std::unique_ptr<CharDeviceInterface> FakeDeviceFactory::NewCharDevice() {
+  return std::unique_ptr<CharDeviceInterface>(new FakeCharDevice());
+}
+
+}  // namespace android
diff --git a/peripheralmanager/daemon/fake_devices.h b/peripheralmanager/daemon/fake_devices.h
new file mode 100644
index 0000000..d1aa7f9
--- /dev/null
+++ b/peripheralmanager/daemon/fake_devices.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef SYSTEM_PERIPHERALMANAGER_DAEMON_FAKE_DEVICES_H_
+#define SYSTEM_PERIPHERALMANAGER_DAEMON_FAKE_DEVICES_H_
+
+#include <string>
+#include <vector>
+
+#include "char_device.h"
+
+namespace android {
+
+class FakeCharDevice : public CharDeviceInterface {
+ public:
+  FakeCharDevice();
+  ~FakeCharDevice() override;
+
+  int Open(const char* pathname, int flags) override;
+  int Close(int fd) override;
+  int Ioctl(int fd, int request, void* argp) override;
+  ssize_t Read(int fd, void* buf, size_t count) override;
+  ssize_t Write(int fd, const void* buf, size_t count) override;
+  int Poll(struct pollfd* fds, nfds_t nfds, int timeout) override;
+};
+
+class FakeDeviceFactory : public CharDeviceFactory {
+ public:
+  FakeDeviceFactory();
+  ~FakeDeviceFactory();
+
+  std::unique_ptr<CharDeviceInterface> NewCharDevice() override;
+};
+
+}  // namespace android
+
+#endif  // SYSTEM_PERIPHERALMANAGER_DAEMON_FAKE_DEVICES_H_
diff --git a/peripheralmanager/daemon/fake_i2c_devices.cc b/peripheralmanager/daemon/fake_i2c_devices.cc
new file mode 100644
index 0000000..6cb7d8c
--- /dev/null
+++ b/peripheralmanager/daemon/fake_i2c_devices.cc
@@ -0,0 +1,103 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "fake_i2c_devices.h"
+
+#include <base/logging.h>
+#include <linux/i2c-dev.h>
+#include <linux/i2c.h>
+
+namespace android {
+
+FakeI2cDevice::FakeI2cDevice() {}
+FakeI2cDevice::~FakeI2cDevice() {}
+
+int FakeI2cDevice::Open(const char* pathname, int flags) {
+  return 1;
+}
+
+int FakeI2cDevice::Close(int fd) {
+  return 0;
+}
+
+int FakeI2cDevice::Ioctl(int fd, int request, void* argp) {
+  if (request == I2C_SMBUS) {
+    struct i2c_smbus_ioctl_data* smbus_args =
+        reinterpret_cast<struct i2c_smbus_ioctl_data*>(argp);
+
+    if (smbus_args->read_write == I2C_SMBUS_WRITE) {
+      uint8_t* data = smbus_args->data->block;
+      std::vector<uint8_t> temp;
+      if (smbus_args->size == I2C_SMBUS_I2C_BLOCK_DATA) {
+        temp.assign(data + 1, data + data[0] + 1);
+      } else if (smbus_args->size == I2C_SMBUS_WORD_DATA) {
+        temp.assign(data, data + 2);
+      } else if (smbus_args->size == I2C_SMBUS_BYTE_DATA) {
+        temp.assign(data, data + 1);
+      }
+
+      registers_.emplace(smbus_args->command, temp);
+      LOG(INFO) << "writing " << temp.size() << " elements in "
+                << smbus_args->command;
+      return 0;
+    } else if (smbus_args->read_write == I2C_SMBUS_READ) {
+      if (!registers_.count(smbus_args->command)) {
+        LOG(INFO) << "no such register";
+        return -1;
+      }
+      auto reg = registers_.find(smbus_args->command);
+      LOG(INFO) << "reading register " << smbus_args->command << " that has "
+                << reg->second.size() << " elements";
+
+      if (smbus_args->size == I2C_SMBUS_I2C_BLOCK_DATA) {
+        memcpy(smbus_args->data->block + 1,
+               reg->second.data(),
+               smbus_args->data->block[0]);
+      } else if (smbus_args->size == I2C_SMBUS_WORD_DATA) {
+        memcpy(smbus_args->data->block, reg->second.data(), 2);
+      } else if (smbus_args->size == I2C_SMBUS_BYTE_DATA) {
+        memcpy(smbus_args->data->block, reg->second.data(), 1);
+      }
+      return 0;
+    }
+  } else if (request == I2C_SLAVE) {
+    return 0;
+  }
+
+  return -1;
+}
+
+ssize_t FakeI2cDevice::Read(int fd, void* buf, size_t count) {
+  return count;
+}
+
+ssize_t FakeI2cDevice::Write(int fd, const void* buf, size_t count) {
+  return count;
+}
+
+int FakeI2cDevice::Poll(struct pollfd* fds, nfds_t nfds, int timeout) {
+  return 0;
+}
+
+FakeI2cDeviceFactory::FakeI2cDeviceFactory() {}
+
+FakeI2cDeviceFactory::~FakeI2cDeviceFactory() {}
+
+std::unique_ptr<CharDeviceInterface> FakeI2cDeviceFactory::NewCharDevice() {
+  return std::unique_ptr<CharDeviceInterface>(new FakeI2cDevice());
+}
+
+}  // namespace android
diff --git a/peripheralmanager/daemon/fake_i2c_devices.h b/peripheralmanager/daemon/fake_i2c_devices.h
new file mode 100644
index 0000000..6072cef
--- /dev/null
+++ b/peripheralmanager/daemon/fake_i2c_devices.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef SYSTEM_PERIPHERALMANAGER_DAEMON_FAKE_I2C_DEVICES_H_
+#define SYSTEM_PERIPHERALMANAGER_DAEMON_FAKE_I2C_DEVICES_H_
+
+#include <map>
+#include <string>
+#include <vector>
+
+#include "char_device.h"
+
+namespace android {
+
+class FakeI2cDevice : public CharDeviceInterface {
+ public:
+  FakeI2cDevice();
+  ~FakeI2cDevice() override;
+
+  int Open(const char* pathname, int flags) override;
+  int Close(int fd) override;
+  int Ioctl(int fd, int request, void* argp) override;
+  ssize_t Read(int fd, void* buf, size_t count) override;
+  ssize_t Write(int fd, const void* buf, size_t count) override;
+  int Poll(struct pollfd* fds, nfds_t nfds, int timeout) override;
+
+ private:
+  std::map<uint8_t, std::vector<uint8_t>> registers_;
+};
+
+class FakeI2cDeviceFactory : public CharDeviceFactory {
+ public:
+  FakeI2cDeviceFactory();
+  ~FakeI2cDeviceFactory();
+
+  std::unique_ptr<CharDeviceInterface> NewCharDevice() override;
+};
+
+}  // namespace android
+
+#endif  // SYSTEM_PERIPHERALMANAGER_DAEMON_FAKE_I2C_DEVICES_H_
diff --git a/peripheralmanager/daemon/gpio_driver.h b/peripheralmanager/daemon/gpio_driver.h
new file mode 100644
index 0000000..084c0f3
--- /dev/null
+++ b/peripheralmanager/daemon/gpio_driver.h
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef SYSTEM_PERIPHERALMANAGER_DAEMON_GPIO_DRIVER_H_
+#define SYSTEM_PERIPHERALMANAGER_DAEMON_GPIO_DRIVER_H_
+
+#include <stdint.h>
+
+#include <memory>
+#include <string>
+
+#include <android-base/unique_fd.h>
+#include <base/macros.h>
+#include <peripheralmanager/constants.h>
+
+namespace android {
+
+// This interface must be implemented by all
+// Gpio drivers.
+class GpioDriverInterface {
+ public:
+  GpioDriverInterface() {}
+  virtual ~GpioDriverInterface() {}
+
+  // TODO(leecam): Init should have generic params.
+  virtual bool Init(uint32_t index) = 0;
+
+  virtual bool SetValue(bool val) = 0;
+  virtual bool GetValue(bool* val) = 0;
+  virtual bool SetActiveType(GpioActiveType type) = 0;
+  virtual bool SetDirection(GpioDirection direction) = 0;
+  virtual bool SetEdgeType(GpioEdgeType type) = 0;
+  virtual bool GetPollingFd(::android::base::unique_fd* fd) = 0;
+};
+
+// The following is driver boilerplate.
+// TODO(leecam): Abstract this into a seperate Driver class.
+class GpioDriverInfoBase {
+ public:
+  GpioDriverInfoBase() {}
+  virtual ~GpioDriverInfoBase() {}
+
+  virtual std::string Compat() = 0;
+  virtual std::unique_ptr<GpioDriverInterface> Probe() = 0;
+};
+
+template <class T, class PARAM>
+class GpioDriverInfo : public GpioDriverInfoBase {
+ public:
+  explicit GpioDriverInfo(PARAM param) : param_(param) {}
+  ~GpioDriverInfo() override {}
+
+  std::string Compat() override { return T::Compat(); }
+
+  std::unique_ptr<GpioDriverInterface> Probe() override {
+    return std::unique_ptr<GpioDriverInterface>(new T(param_));
+  }
+
+ private:
+  PARAM param_;
+};
+
+}  // namespace android
+
+#endif  // SYSTEM_PERIPHERALMANAGER_DAEMON_GPIO_DRIVER_H_
diff --git a/peripheralmanager/daemon/gpio_driver_mock.h b/peripheralmanager/daemon/gpio_driver_mock.h
new file mode 100644
index 0000000..f52b0f1
--- /dev/null
+++ b/peripheralmanager/daemon/gpio_driver_mock.h
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef SYSTEM_PERIPHERALMANAGER_DAEMON_GPIO_DRIVER_MOCK_H_
+#define SYSTEM_PERIPHERALMANAGER_DAEMON_GPIO_DRIVER_MOCK_H_
+
+#include <stdint.h>
+
+#include <base/macros.h>
+#include <gmock/gmock.h>
+
+#include "gpio_driver.h"
+
+namespace android {
+
+class GpioDriverMock : public GpioDriverInterface {
+ public:
+  explicit GpioDriverMock(void* arg) : is_input(true) {}
+  ~GpioDriverMock() {}
+
+  static std::string Compat() { return "GPIOSYSFS"; }
+
+  bool Init(uint32_t index) { return true; }
+
+  bool SetValue(bool val) { return !is_input; };
+
+  bool GetValue(bool* val) { return true; };
+  bool SetActiveType(GpioActiveType type) { return true; };
+
+  bool SetDirection(GpioDirection direction) {
+    is_input = direction == kDirectionIn;
+    return true;
+  };
+
+  bool SetEdgeType(GpioEdgeType type) { return true; };
+  bool GetPollingFd(::android::base::unique_fd* fd) { return true; };
+
+ private:
+  bool is_input;
+  DISALLOW_COPY_AND_ASSIGN(GpioDriverMock);
+};
+
+}  // namespace android
+
+#endif  // SYSTEM_PERIPHERALMANAGER_DAEMON_GPIO_DRIVER_MOCK_H_
diff --git a/peripheralmanager/daemon/gpio_driver_sysfs.cc b/peripheralmanager/daemon/gpio_driver_sysfs.cc
new file mode 100644
index 0000000..b49c2ff
--- /dev/null
+++ b/peripheralmanager/daemon/gpio_driver_sysfs.cc
@@ -0,0 +1,221 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "gpio_driver_sysfs.h"
+
+#include <fcntl.h>
+#include <string>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include <base/logging.h>
+
+namespace android {
+namespace {
+
+// Path to sysfd gpio.
+const char kSysfsGpioPathPrefix[] = "/sys/class/gpio/gpio";
+
+// Path to export file.
+const char kSysfsGpioExportPath[] = "/sys/class/gpio/export";
+
+// Direction filename.
+const char kDirection[] = "direction";
+
+// Value filename.
+const char kValue[] = "value";
+
+// Active low filename.
+const char kActiveLowFile[] = "active_low";
+
+// Edge filename.
+const char kEdge[] = "edge";
+
+// Edge values.
+const char kEdgeNoneValue[] = "none";
+const char kEdgeRisingValue[] = "rising";
+const char kEdgeFallingValue[] = "falling";
+const char kEdgeBothValue[] = "both";
+
+// Direction values
+const char kDirHigh[] = "high";
+const char kDirLow[] = "low";
+const char kDirIn[] = "in";
+
+// Value values.
+const char kValueHigh[] = "1";
+const char kValueLow[] = "0";
+
+}  // namespace
+
+GpioDriverSysfs::GpioDriverSysfs(void* arg) : fd_(-1) {}
+
+GpioDriverSysfs::~GpioDriverSysfs() {
+  if (fd_ >= 0) {
+    close(fd_);
+  }
+}
+
+bool GpioDriverSysfs::Init(uint32_t index) {
+  if (!ExportGpio(index)) {
+    LOG(WARNING) << "GpioDriverSysfs: Failed to export " << index;
+    return false;
+  }
+  std::string path = kSysfsGpioPathPrefix + std::to_string(index);
+
+  int fd = open(path.c_str(), O_RDONLY);
+  if (fd < 0) {
+    PLOG(WARNING) << "Failed to open " << path;
+    return false;
+  }
+
+  fd_ = fd;
+  return true;
+}
+
+bool GpioDriverSysfs::SetValue(bool val) {
+  bool success = val ? Enable() : Disable();
+  if (!success) {
+    LOG(WARNING) << "Failed to set the value of the GPIO. Is it configured as "
+                 << "output?";
+  }
+  return success;
+}
+
+bool GpioDriverSysfs::GetValue(bool* val) {
+  std::string read_val;
+  if (!ReadFromFile(kValue, &read_val))
+    return false;
+  if (read_val.size() < 1) {
+    return false;
+  }
+  // Remove any whitespace.
+  read_val = read_val[0];
+  if (read_val == kValueHigh)
+    *val = true;
+  else
+    *val = false;
+  return true;
+}
+
+bool GpioDriverSysfs::SetDirection(GpioDirection direction) {
+  switch (direction) {
+    case kDirectionIn:
+      return WriteToFile(kDirection, kDirIn);
+    case kDirectionOutInitiallyHigh:
+      return WriteToFile(kDirection, kDirHigh);
+    case kDirectionOutInitiallyLow:
+      return WriteToFile(kDirection, kDirLow);
+  }
+  return false;
+}
+
+bool GpioDriverSysfs::SetActiveType(GpioActiveType type) {
+  if (type == kActiveLow) {
+    return WriteToFile(kActiveLowFile, kValueLow);
+  } else if (type == kActiveHigh) {
+    return WriteToFile(kActiveLowFile, kValueHigh);
+  }
+  return false;
+}
+
+bool GpioDriverSysfs::SetEdgeType(GpioEdgeType type) {
+  switch (type) {
+    case kEdgeNone:
+      return WriteToFile(kEdge, kEdgeNoneValue);
+    case kEdgeRising:
+      return WriteToFile(kEdge, kEdgeRisingValue);
+    case kEdgeFalling:
+      return WriteToFile(kEdge, kEdgeFallingValue);
+    case kEdgeBoth:
+      return WriteToFile(kEdge, kEdgeBothValue);
+  }
+  return false;
+}
+
+bool GpioDriverSysfs::GetPollingFd(::android::base::unique_fd* fd) {
+  int f = openat(fd_, kValue, O_RDWR);
+  if (f < 0)
+    return false;
+
+  fd->reset(f);
+  return true;
+}
+
+bool GpioDriverSysfs::Enable() {
+  return WriteToFile(kValue, kValueHigh);
+}
+
+bool GpioDriverSysfs::Disable() {
+  return WriteToFile(kValue, kValueLow);
+}
+
+bool GpioDriverSysfs::WriteToFile(const std::string& file,
+                                  const std::string& value) {
+  int fd = openat(fd_, file.c_str(), O_RDWR);
+  if (fd < 0)
+    return false;
+
+  ssize_t bytes = write(fd, value.c_str(), value.size());
+  close(fd);
+  if (bytes < 0)
+    return false;
+  if ((size_t)bytes != value.size())
+    return false;
+  return true;
+}
+
+bool GpioDriverSysfs::ReadFromFile(const std::string& file,
+                                   std::string* value) {
+  int fd = openat(fd_, file.c_str(), O_RDONLY);
+  if (fd < 0)
+    return false;
+  char tmp_buf[16] = "";
+  ssize_t bytes = read(fd, tmp_buf, sizeof(tmp_buf));
+  close(fd);
+  if (bytes < 0)
+    return false;
+  value->assign(tmp_buf, bytes);
+  return true;
+}
+
+bool GpioDriverSysfs::ExportGpio(uint32_t index) {
+  // Check if the pin is already exported.
+  // It will fail otherwise.
+  std::string path = kSysfsGpioPathPrefix + std::to_string(index);
+  struct stat stat_buf;
+  if (!stat(path.c_str(), &stat_buf))
+    return true;
+
+  int fd = open(kSysfsGpioExportPath, O_WRONLY);
+  if (fd < 0) {
+    PLOG(WARNING) << "Failed to open " << kSysfsGpioExportPath;
+    return false;
+  }
+  std::string value = std::to_string(index);
+  ssize_t bytes = write(fd, value.c_str(), value.size());
+  close(fd);
+  if (bytes < 0) {
+    PLOG(WARNING) << "Failed to write " << bytes;
+    return false;
+  }
+  if ((size_t)bytes != value.size())
+    return false;
+  return true;
+}
+
+}  // namespace android
diff --git a/peripheralmanager/daemon/gpio_driver_sysfs.h b/peripheralmanager/daemon/gpio_driver_sysfs.h
new file mode 100644
index 0000000..690066a
--- /dev/null
+++ b/peripheralmanager/daemon/gpio_driver_sysfs.h
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef SYSTEM_PERIPHERALMANAGER_DAEMON_GPIO_DRIVER_SYSFS_H_
+#define SYSTEM_PERIPHERALMANAGER_DAEMON_GPIO_DRIVER_SYSFS_H_
+
+#include <stdint.h>
+
+#include <base/macros.h>
+
+#include "gpio_driver.h"
+
+namespace android {
+
+class GpioDriverSysfs : public GpioDriverInterface {
+ public:
+  explicit GpioDriverSysfs(void* arg);
+  ~GpioDriverSysfs();
+
+  static std::string Compat() { return "GPIOSYSFS"; }
+
+  bool Init(uint32_t index) override;
+
+  // Gpio Driver interface.
+  bool SetValue(bool val) override;
+  bool GetValue(bool* val) override;
+  bool SetActiveType(GpioActiveType type) override;
+  bool SetDirection(GpioDirection direction) override;
+  bool SetEdgeType(GpioEdgeType type) override;
+  bool GetPollingFd(::android::base::unique_fd* fd) override;
+
+ private:
+  bool Enable();
+  bool Disable();
+  bool ExportGpio(uint32_t index);
+  bool WriteToFile(const std::string& file, const std::string& value);
+  bool ReadFromFile(const std::string& file, std::string* value);
+
+  int fd_;
+
+  DISALLOW_COPY_AND_ASSIGN(GpioDriverSysfs);
+};
+
+}  // namespace android
+
+#endif  // SYSTEM_PERIPHERALMANAGER_DAEMON_GPIO_DRIVER_SYSFS_H_
diff --git a/peripheralmanager/daemon/gpio_manager.cc b/peripheralmanager/daemon/gpio_manager.cc
new file mode 100644
index 0000000..1a47941
--- /dev/null
+++ b/peripheralmanager/daemon/gpio_manager.cc
@@ -0,0 +1,114 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "gpio_manager.h"
+
+#include <base/logging.h>
+
+namespace android {
+
+std::unique_ptr<GpioManager> g_gpio_manager;
+
+GpioManager::GpioManager() {}
+
+GpioManager::~GpioManager() {}
+
+// static
+GpioManager* GpioManager::GetGpioManager() {
+  if (!g_gpio_manager) {
+    g_gpio_manager.reset(new GpioManager());
+  }
+  return g_gpio_manager.get();
+}
+
+void GpioManager::ResetGpioManager() {
+  g_gpio_manager.reset();
+}
+
+bool GpioManager::RegisterGpioSysfs(const std::string& name, uint32_t index) {
+  if (sysfs_pins_.count(name))
+    return false;
+  sysfs_pins_[name].index = index;
+  return true;
+}
+
+bool GpioManager::SetPinMux(const std::string& name, const std::string& mux) {
+  if (!sysfs_pins_.count(name))
+    return false;
+  sysfs_pins_[name].mux = mux;
+  return true;
+}
+
+std::vector<std::string> GpioManager::GetGpioPins() {
+  std::vector<std::string> pins;
+  for (auto& i : sysfs_pins_)
+    pins.push_back(i.first);
+  return pins;
+}
+
+bool GpioManager::HasGpio(const std::string& pin_name) {
+  return sysfs_pins_.count(pin_name);
+}
+
+bool GpioManager::RegisterDriver(
+    std::unique_ptr<GpioDriverInfoBase> driver_info) {
+  std::string key = driver_info->Compat();
+  driver_infos_[key] = std::move(driver_info);
+  return true;
+}
+
+std::unique_ptr<GpioPin> GpioManager::OpenGpioPin(const std::string& name) {
+  // Get the Pin  from the BSP.
+  auto pin_it = sysfs_pins_.find(name);
+  if (pin_it == sysfs_pins_.end()) {
+    LOG(WARNING) << "GpioManager: Pin not found. " << name;
+    return nullptr;
+  }
+
+  // Check its not alread in use
+  if (pin_it->second.driver_) {
+    LOG(WARNING) << "GpioManager: Pin in use. " << name;
+    return nullptr;
+  }
+
+  // Find a driver.
+  // Currently there is only hardcoded support for GPIOSYSFS
+  auto driver_info_it = driver_infos_.find("GPIOSYSFS");
+
+  // Fail if there is no driver.
+  if (driver_info_it == driver_infos_.end()) {
+    LOG(WARNING) << "GpioManager: Failed to find driver " << name;
+    return nullptr;
+  }
+
+  std::unique_ptr<GpioDriverInterface> driver(driver_info_it->second->Probe());
+
+  // Set pin mux
+  if (!pin_it->second.mux.empty()) {
+    PinMuxManager::GetPinMuxManager()->SetGpio(pin_it->second.mux);
+  }
+
+  if (!driver->Init(pin_it->second.index)) {
+    LOG(WARNING) << "GpioManager: Failed to init driver " << name;
+    return nullptr;
+  }
+
+  pin_it->second.driver_ = std::move(driver);
+
+  return std::unique_ptr<GpioPin>(new GpioPin(&(pin_it->second)));
+}
+
+}  // namespace android
diff --git a/peripheralmanager/daemon/gpio_manager.h b/peripheralmanager/daemon/gpio_manager.h
new file mode 100644
index 0000000..52bd779
--- /dev/null
+++ b/peripheralmanager/daemon/gpio_manager.h
@@ -0,0 +1,119 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef SYSTEM_PERIPHERALMANAGER_DAEMON_GPIO_MANAGER_H_
+#define SYSTEM_PERIPHERALMANAGER_DAEMON_GPIO_MANAGER_H_
+
+#include <stdint.h>
+
+#include <map>
+#include <memory>
+#include <string>
+#include <vector>
+
+#include <base/macros.h>
+
+#include "gpio_driver.h"
+#include "pin_mux_manager.h"
+
+namespace android {
+
+struct GpioPinSysfs {
+  uint32_t index;
+  std::string mux;
+  std::unique_ptr<GpioDriverInterface> driver_;
+};
+
+class GpioPin {
+ public:
+  // TODO(leecam): pins should have a generic device
+  // reference, not a sysfs one.
+  explicit GpioPin(GpioPinSysfs* pin) : pin_(pin) {}
+  ~GpioPin() {
+    if (!pin_->mux.empty()) {
+      PinMuxManager::GetPinMuxManager()->ReleaseGpio(pin_->mux);
+    }
+    pin_->driver_.reset();
+  }
+
+  bool SetValue(bool val) { return pin_->driver_->SetValue(val); }
+
+  bool GetValue(bool* val) { return pin_->driver_->GetValue(val); }
+
+  bool SetDirection(GpioDirection direction) {
+    if (!pin_->mux.empty()) {
+      bool dir = true;
+      if (direction == kDirectionIn)
+        dir = false;
+      if (!PinMuxManager::GetPinMuxManager()->SetGpioDirection(pin_->mux,
+                                                               dir)) {
+        return false;
+      }
+    }
+    return pin_->driver_->SetDirection(direction);
+  }
+
+  bool SetActiveType(GpioActiveType type) {
+    return pin_->driver_->SetActiveType(type);
+  }
+
+  bool SetEdgeType(GpioEdgeType type) {
+    return pin_->driver_->SetEdgeType(type);
+  }
+
+  bool GetPollingFd(::android::base::unique_fd* fd) {
+    return pin_->driver_->GetPollingFd(fd);
+  }
+
+ private:
+  GpioPinSysfs* pin_;
+};
+
+class GpioManager {
+ public:
+  friend class GpioManagerTest;
+  ~GpioManager();
+
+  // Get the singleton.
+  static GpioManager* GetGpioManager();
+
+  // Delete the GpioManager (used for test);
+  static void ResetGpioManager();
+
+  // Used by the BSP to tell PMan of an GPIO Pin.
+  bool RegisterGpioSysfs(const std::string& name, uint32_t index);
+  bool SetPinMux(const std::string& name, const std::string& mux);
+
+  // Query for available pins.
+  std::vector<std::string> GetGpioPins();
+  bool HasGpio(const std::string& pin_name);
+
+  bool RegisterDriver(std::unique_ptr<GpioDriverInfoBase> driver_info);
+
+  std::unique_ptr<GpioPin> OpenGpioPin(const std::string& name);
+
+ private:
+  GpioManager();
+
+  std::map<std::string, std::unique_ptr<GpioDriverInfoBase>> driver_infos_;
+  std::map<std::string, GpioPinSysfs> sysfs_pins_;
+
+  DISALLOW_COPY_AND_ASSIGN(GpioManager);
+};
+
+}  // namespace android
+
+#endif  // SYSTEM_PERIPHERALMANAGER_DAEMON_GPIO_MANAGER_H_
diff --git a/peripheralmanager/daemon/gpio_manager_unittest.cc b/peripheralmanager/daemon/gpio_manager_unittest.cc
new file mode 100644
index 0000000..0e7b07b
--- /dev/null
+++ b/peripheralmanager/daemon/gpio_manager_unittest.cc
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdio.h>
+
+#include <gtest/gtest.h>
+
+#include "gpio_driver_sysfs.h"
+#include "gpio_manager.h"
+
+namespace android {
+
+class GpioManagerTest : public ::testing::Test {
+ public:
+  GpioManagerTest() {}
+  ~GpioManagerTest() = default;
+
+ protected:
+  GpioManager manager;
+};
+
+TEST_F(GpioManagerTest, RegisterDriver) {
+  manager.RegisterDriver(std::unique_ptr<GpioDriverInfoBase>(
+      new GpioDriverInfo<GpioDriverSysfs, void*>(nullptr)));
+}
+
+TEST_F(GpioManagerTest, BasicOpen) {
+  manager.RegisterDriver(std::unique_ptr<GpioDriverInfoBase>(
+      new GpioDriverInfo<GpioDriverSysfs, void*>(nullptr)));
+
+  manager.RegisterGpioSysfs("IO11", 40);
+
+  std::unique_ptr<GpioPin> pin(manager.OpenGpioPin("IO11"));
+}
+
+// TODO(leecam): Once this stablizes and has a stub,
+// write lots more tests.
+
+}  // namespace android
\ No newline at end of file
diff --git a/peripheralmanager/daemon/i2c_driver.h b/peripheralmanager/daemon/i2c_driver.h
new file mode 100644
index 0000000..7eac065
--- /dev/null
+++ b/peripheralmanager/daemon/i2c_driver.h
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef SYSTEM_PERIPHERALMANAGER_DAEMON_I2C_DRIVER_H_
+#define SYSTEM_PERIPHERALMANAGER_DAEMON_I2C_DRIVER_H_
+
+#include <stdint.h>
+
+#include <memory>
+#include <string>
+
+#include <base/macros.h>
+
+#include "peripheralmanager/constants.h"
+
+namespace android {
+
+class I2cDriverInterface {
+ public:
+  I2cDriverInterface() {}
+  virtual ~I2cDriverInterface() {}
+
+  // TODO(leecam): Init should have generic params.
+  virtual bool Init(uint32_t bus_id, uint32_t address) = 0;
+
+  // Returns 0 on success, errno on errors.
+  virtual int32_t Read(void* data, uint32_t size, uint32_t* bytes_read) = 0;
+  virtual int32_t ReadRegByte(uint8_t reg, uint8_t* val) = 0;
+  virtual int32_t ReadRegWord(uint8_t reg, uint16_t* val) = 0;
+  virtual int32_t ReadRegBuffer(uint8_t reg,
+                                uint8_t* data,
+                                uint32_t size,
+                                uint32_t* bytes_read) = 0;
+
+  virtual int32_t Write(const void* data,
+                        uint32_t size,
+                        uint32_t* bytes_written) = 0;
+  virtual int32_t WriteRegByte(uint8_t reg, uint8_t val) = 0;
+  virtual int32_t WriteRegWord(uint8_t reg, uint16_t val) = 0;
+  virtual int32_t WriteRegBuffer(uint8_t reg,
+                                 const uint8_t* data,
+                                 uint32_t size,
+                                 uint32_t* bytes_written) = 0;
+};
+
+class I2cDriverInfoBase {
+ public:
+  I2cDriverInfoBase() {}
+  virtual ~I2cDriverInfoBase() {}
+
+  virtual std::string Compat() = 0;
+  virtual std::unique_ptr<I2cDriverInterface> Probe() = 0;
+};
+
+template <class T, class PARAM>
+class I2cDriverInfo : public I2cDriverInfoBase {
+ public:
+  explicit I2cDriverInfo(PARAM param) : param_(param) {}
+  ~I2cDriverInfo() override {}
+
+  std::string Compat() override { return T::Compat(); }
+
+  std::unique_ptr<I2cDriverInterface> Probe() override {
+    return std::unique_ptr<I2cDriverInterface>(new T(param_));
+  }
+
+ private:
+  PARAM param_;
+};
+
+}  // namespace android
+
+#endif  // SYSTEM_PERIPHERALMANAGER_DAEMON_I2C_DRIVER_H_
diff --git a/peripheralmanager/daemon/i2c_driver_i2cdev.cc b/peripheralmanager/daemon/i2c_driver_i2cdev.cc
new file mode 100644
index 0000000..b4f2280
--- /dev/null
+++ b/peripheralmanager/daemon/i2c_driver_i2cdev.cc
@@ -0,0 +1,207 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "i2c_driver_i2cdev.h"
+
+#include <fcntl.h>
+#include <linux/i2c.h>
+#include <linux/i2c-dev.h>
+#include <sys/ioctl.h>
+#include <string>
+
+#include <base/logging.h>
+
+namespace android {
+namespace {
+
+const char kI2cDevPath[] = "/dev/i2c-";
+
+}  // namespace
+
+I2cDriverI2cDev::I2cDriverI2cDev(CharDeviceFactory* char_device_factory)
+    : fd_(-1), char_device_factory_(char_device_factory) {}
+
+I2cDriverI2cDev::~I2cDriverI2cDev() {
+  if (fd_ >= 0 && char_interface_ != nullptr) {
+    char_interface_->Close(fd_);
+  }
+}
+
+bool I2cDriverI2cDev::Init(uint32_t bus_id, uint32_t address) {
+  if (fd_ >= 0) {
+    return false;
+  }
+  // Get a char device. If char_device_factory_ is set
+  // then this is a unittest and the char device is provided
+  // by the test. Otherwise create a normal CharDevice.
+  if (!char_device_factory_) {
+    char_interface_.reset(new CharDevice());
+  } else {
+    char_interface_ = char_device_factory_->NewCharDevice();
+  }
+
+  std::string path = kI2cDevPath + std::to_string(bus_id);
+
+  int fd = char_interface_->Open(path.c_str(), O_RDWR);
+  if (fd < 0)
+    return false;
+  uintptr_t tmp_addr = address;
+  if (char_interface_->Ioctl(fd, I2C_SLAVE, (void*)tmp_addr) < 0) {
+    LOG(ERROR) << "Failed to set I2C slave";
+    char_interface_->Close(fd);
+    return false;
+  }
+
+  fd_ = fd;
+
+  return true;
+}
+
+int32_t I2cDriverI2cDev::Read(void* data, uint32_t size, uint32_t* bytes_read) {
+  *bytes_read = char_interface_->Read(fd_, data, size);
+  return *bytes_read == size ? 0 : EIO;
+}
+
+int32_t I2cDriverI2cDev::ReadRegByte(uint8_t reg, uint8_t* val) {
+  union i2c_smbus_data read_data;
+  struct i2c_smbus_ioctl_data smbus_args {
+    .command = reg, .read_write = I2C_SMBUS_READ, .size = I2C_SMBUS_BYTE_DATA,
+    .data = &read_data,
+  };
+
+  if (char_interface_->Ioctl(fd_, I2C_SMBUS, &smbus_args) < 0) {
+    LOG(INFO) << "Failed I2C_SMBUS";
+    return EIO;
+  }
+
+  *val = read_data.byte;
+  return 0;
+}
+
+int32_t I2cDriverI2cDev::ReadRegWord(uint8_t reg, uint16_t* val) {
+  union i2c_smbus_data read_data;
+  struct i2c_smbus_ioctl_data smbus_args {
+    .command = reg, .read_write = I2C_SMBUS_READ, .size = I2C_SMBUS_WORD_DATA,
+    .data = &read_data,
+  };
+
+  if (char_interface_->Ioctl(fd_, I2C_SMBUS, &smbus_args) < 0) {
+    LOG(INFO) << "Failed I2C_SMBUS";
+    return EIO;
+  }
+
+  *val = read_data.word;
+  return 0;
+}
+
+int32_t I2cDriverI2cDev::ReadRegBuffer(uint8_t reg,
+                                       uint8_t* data,
+                                       uint32_t size,
+                                       uint32_t* bytes_read) {
+  *bytes_read = 0;
+  if (size > I2C_SMBUS_BLOCK_MAX) {
+    LOG(WARNING) << "Can't read more than 32 bytes at a time.";
+    return EINVAL;
+  }
+
+  union i2c_smbus_data read_data;
+  read_data.block[0] = size;
+
+  struct i2c_smbus_ioctl_data smbus_args;
+  smbus_args.command = reg;
+  smbus_args.read_write = I2C_SMBUS_READ;
+  smbus_args.size = I2C_SMBUS_I2C_BLOCK_DATA;
+  smbus_args.data = &read_data;
+
+  if (char_interface_->Ioctl(fd_, I2C_SMBUS, &smbus_args) < 0) {
+    LOG(ERROR) << "Failed I2C_SMBUS";
+    return EIO;
+  }
+
+  memcpy(data, &read_data.block[1], size);
+  *bytes_read = size;
+
+  return 0;
+}
+
+int32_t I2cDriverI2cDev::Write(const void* data,
+                               uint32_t size,
+                               uint32_t* bytes_written) {
+  *bytes_written = char_interface_->Write(fd_, data, size);
+  return *bytes_written == size ? 0 : EIO;
+}
+
+int32_t I2cDriverI2cDev::WriteRegByte(uint8_t reg, uint8_t val) {
+  union i2c_smbus_data write_data;
+  write_data.byte = val;
+  struct i2c_smbus_ioctl_data smbus_args;
+  smbus_args.command = reg;
+  smbus_args.read_write = I2C_SMBUS_WRITE;
+  smbus_args.size = I2C_SMBUS_BYTE_DATA;
+  smbus_args.data = &write_data;
+
+  if (char_interface_->Ioctl(fd_, I2C_SMBUS, &smbus_args) < 0) {
+    return EIO;
+  }
+  return 0;
+}
+
+int32_t I2cDriverI2cDev::WriteRegWord(uint8_t reg, uint16_t val) {
+  union i2c_smbus_data write_data;
+  write_data.word = val;
+  struct i2c_smbus_ioctl_data smbus_args;
+  smbus_args.command = reg;
+  smbus_args.read_write = I2C_SMBUS_WRITE;
+  smbus_args.size = I2C_SMBUS_WORD_DATA;
+  smbus_args.data = &write_data;
+
+  if (char_interface_->Ioctl(fd_, I2C_SMBUS, &smbus_args) < 0) {
+    return EIO;
+  }
+  return 0;
+}
+
+int32_t I2cDriverI2cDev::WriteRegBuffer(uint8_t reg,
+                                        const uint8_t* data,
+                                        uint32_t size,
+                                        uint32_t* bytes_written) {
+  *bytes_written = 0;
+  if (size > I2C_SMBUS_BLOCK_MAX) {
+    LOG(WARNING) << "Can't write more than 32 bytes at a time.";
+    return EINVAL;
+  }
+
+  union i2c_smbus_data write_data;
+  write_data.block[0] = size;
+  memcpy(&write_data.block[1], data, size);
+
+  struct i2c_smbus_ioctl_data smbus_args;
+  smbus_args.command = reg;
+  smbus_args.read_write = I2C_SMBUS_WRITE;
+  smbus_args.size = I2C_SMBUS_I2C_BLOCK_DATA;
+  smbus_args.data = &write_data;
+
+  if (char_interface_->Ioctl(fd_, I2C_SMBUS, &smbus_args) < 0) {
+    LOG(ERROR) << "Failed I2C_SMBUS";
+    return EIO;
+  }
+
+  *bytes_written = size;
+
+  return 0;
+}
+
+}  // namespace
diff --git a/peripheralmanager/daemon/i2c_driver_i2cdev.h b/peripheralmanager/daemon/i2c_driver_i2cdev.h
new file mode 100644
index 0000000..8282b47
--- /dev/null
+++ b/peripheralmanager/daemon/i2c_driver_i2cdev.h
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef SYSTEM_PERIPHERALMANAGER_DAEMON_I2C_DRIVER_I2CDEV_H_
+#define SYSTEM_PERIPHERALMANAGER_DAEMON_I2C_DRIVER_I2CDEV_H_
+
+#include <stdint.h>
+
+#include <memory>
+
+#include <base/macros.h>
+
+#include "char_device.h"
+#include "i2c_driver.h"
+
+namespace android {
+
+class I2cDriverI2cDev : public I2cDriverInterface {
+ public:
+  explicit I2cDriverI2cDev(CharDeviceFactory* char_device_factory);
+  ~I2cDriverI2cDev();
+
+  static std::string Compat() { return "I2CDEV"; }
+
+  bool Init(uint32_t bus_id, uint32_t address) override;
+
+  int32_t Read(void* data, uint32_t size, uint32_t* bytes_read) override;
+  int32_t ReadRegByte(uint8_t reg, uint8_t* val) override;
+  int32_t ReadRegWord(uint8_t reg, uint16_t* val) override;
+  int32_t ReadRegBuffer(uint8_t reg,
+                        uint8_t* data,
+                        uint32_t size,
+                        uint32_t* bytes_read) override;
+
+  int32_t Write(const void* data,
+                uint32_t size,
+                uint32_t* bytes_written) override;
+  int32_t WriteRegByte(uint8_t reg, uint8_t val) override;
+  int32_t WriteRegWord(uint8_t reg, uint16_t val) override;
+  int32_t WriteRegBuffer(uint8_t reg,
+                         const uint8_t* data,
+                         uint32_t size,
+                         uint32_t* bytes_written) override;
+
+ private:
+  int fd_;
+
+  // Used for unit testing and is null in production.
+  // Ownership is in the test and outlives this class.
+  CharDeviceFactory* char_device_factory_;
+  std::unique_ptr<CharDeviceInterface> char_interface_;
+  DISALLOW_COPY_AND_ASSIGN(I2cDriverI2cDev);
+};
+
+}  // namespace android
+
+#endif  // SYSTEM_PERIPHERALMANAGER_DAEMON_I2C_DRIVER_I2CDEV_H_
diff --git a/peripheralmanager/daemon/i2c_manager.cc b/peripheralmanager/daemon/i2c_manager.cc
new file mode 100644
index 0000000..7ca084e
--- /dev/null
+++ b/peripheralmanager/daemon/i2c_manager.cc
@@ -0,0 +1,126 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "i2c_manager.h"
+
+#include <base/logging.h>
+
+#include "pin_mux_manager.h"
+
+namespace android {
+
+std::unique_ptr<I2cManager> g_i2c_manager;
+
+I2cManager::I2cManager() {}
+
+I2cManager::~I2cManager() {}
+
+// static
+I2cManager* I2cManager::GetI2cManager() {
+  if (!g_i2c_manager) {
+    g_i2c_manager.reset(new I2cManager());
+  }
+  return g_i2c_manager.get();
+}
+
+// static
+void I2cManager::ResetI2cManager() {
+  g_i2c_manager.reset();
+}
+
+bool I2cManager::RegisterI2cDevBus(const std::string& name,
+                                   uint32_t bus) {
+  if (i2cdev_buses_.count(name))
+    return false;
+  i2cdev_buses_.emplace(name, I2cDevBus(bus));
+  return true;
+}
+
+std::vector<std::string> I2cManager::GetI2cDevBuses() {
+  std::vector<std::string> buses;
+  for (auto& i : i2cdev_buses_)
+    buses.push_back(i.first);
+  return buses;
+}
+
+bool I2cManager::HasI2cDevBus(const std::string& name) {
+  return i2cdev_buses_.count(name);
+}
+
+bool I2cManager::RegisterDriver(
+    std::unique_ptr<I2cDriverInfoBase> driver_info) {
+  std::string key = driver_info->Compat();
+  driver_infos_[key] = std::move(driver_info);
+  return true;
+}
+
+bool I2cManager::SetPinMux(const std::string& name, const std::string& mux) {
+  auto bus_it = i2cdev_buses_.find(name);
+  if (bus_it == i2cdev_buses_.end())
+    return false;
+  bus_it->second.mux = mux;
+  bus_it->second.mux_group = mux;
+  return true;
+}
+
+bool I2cManager::SetPinMuxWithGroup(const std::string& name,
+                                    const std::string& mux,
+                                    const std::string& group) {
+  auto bus_it = i2cdev_buses_.find(name);
+  if (bus_it == i2cdev_buses_.end())
+    return false;
+  bus_it->second.mux = mux;
+  bus_it->second.mux_group = group;
+  return true;
+}
+
+std::unique_ptr<I2cDevice> I2cManager::OpenI2cDevice(const std::string& name, uint32_t address) {
+  LOG(INFO) << "OpenI2cDevice " << name << " " << address;
+  // Get the Bus from the BSP.
+  auto bus_it = i2cdev_buses_.find(name);
+  if (bus_it == i2cdev_buses_.end())
+    return nullptr;
+
+  // Check its not already in use
+  if (bus_it->second.driver_.count(address)) {
+    return nullptr;
+  }
+
+  // Find a driver.
+  // Currently there is only hardcoded support for I2CDEV
+  auto driver_info_it = driver_infos_.find("I2CDEV");
+
+  // Fail if there is no driver.
+  if (driver_info_it == driver_infos_.end())
+    return nullptr;
+
+  std::unique_ptr<I2cDriverInterface> driver(driver_info_it->second->Probe());
+
+  if (!driver->Init(bus_it->second.bus, address))
+    return nullptr;
+
+  // Set Pin muxing.
+  if (!bus_it->second.mux.empty()) {
+    PinMuxManager::GetPinMuxManager()->SetSource(bus_it->second.mux,
+                                                 bus_it->second.mux_group);
+  }
+
+  bus_it->second.driver_[address] = std::move(driver);
+
+  return std::unique_ptr<I2cDevice>(new I2cDevice(&(bus_it->second), address));
+}
+
+}  // namespace android
diff --git a/peripheralmanager/daemon/i2c_manager.h b/peripheralmanager/daemon/i2c_manager.h
new file mode 100644
index 0000000..5627b4d
--- /dev/null
+++ b/peripheralmanager/daemon/i2c_manager.h
@@ -0,0 +1,135 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef SYSTEM_PERIPHERALMANAGER_DAEMON_I2C_MANAGER_H_
+#define SYSTEM_PERIPHERALMANAGER_DAEMON_I2C_MANAGER_H_
+
+#include <stdint.h>
+
+#include <map>
+#include <memory>
+#include <string>
+#include <vector>
+
+#include <base/macros.h>
+
+#include "peripheralmanager/constants.h"
+#include "pin_mux_manager.h"
+#include "i2c_driver.h"
+
+namespace android {
+
+struct I2cDevBus {
+  explicit I2cDevBus(uint32_t b) : bus(b) {}
+  uint32_t bus;
+  std::string mux;
+  std::string mux_group;
+  std::map<uint32_t, std::unique_ptr<I2cDriverInterface>> driver_;
+};
+
+class I2cDevice {
+ public:
+  I2cDevice(I2cDevBus* bus, uint32_t address) : bus_(bus), address_(address) {}
+  ~I2cDevice() {
+    if (!bus_->mux.empty()) {
+      PinMuxManager::GetPinMuxManager()->ReleaseSource(bus_->mux,
+                                                       bus_->mux_group);
+    }
+    bus_->driver_.erase(address_);
+  }
+
+  int32_t Read(void* data, uint32_t size, uint32_t* bytes_read) {
+    return bus_->driver_[address_]->Read(data, size, bytes_read);
+  }
+
+  int32_t ReadRegByte(uint8_t reg, uint8_t* val) {
+    return bus_->driver_[address_]->ReadRegByte(reg, val);
+  }
+
+  int32_t ReadRegWord(uint8_t reg, uint16_t* val) {
+    return bus_->driver_[address_]->ReadRegWord(reg, val);
+  }
+
+  int32_t ReadRegBuffer(uint8_t reg,
+                        uint8_t* data,
+                        uint32_t size,
+                        uint32_t* bytes_read) {
+    return bus_->driver_[address_]->ReadRegBuffer(reg, data, size, bytes_read);
+  }
+
+  int32_t Write(const void* data, uint32_t size, uint32_t* bytes_written) {
+    return bus_->driver_[address_]->Write(data, size, bytes_written);
+  }
+
+  int32_t WriteRegByte(uint8_t reg, uint8_t val) {
+    return bus_->driver_[address_]->WriteRegByte(reg, val);
+  }
+
+  int32_t WriteRegWord(uint8_t reg, uint16_t val) {
+    return bus_->driver_[address_]->WriteRegWord(reg, val);
+  }
+
+  int32_t WriteRegBuffer(uint8_t reg,
+                         const uint8_t* data,
+                         uint32_t size,
+                         uint32_t* bytes_written) {
+    return bus_->driver_[address_]->WriteRegBuffer(
+        reg, data, size, bytes_written);
+  }
+
+ private:
+  I2cDevBus* bus_;
+  uint32_t address_;
+};
+
+class I2cManager {
+ public:
+  friend class I2cManagerTest;
+  ~I2cManager();
+
+  // Get the singleton.
+  static I2cManager* GetI2cManager();
+
+  // Resets the global I2c manager (used for testing).
+  static void ResetI2cManager();
+
+  bool RegisterI2cDevBus(const std::string& name, uint32_t bus);
+
+  std::vector<std::string> GetI2cDevBuses();
+  bool HasI2cDevBus(const std::string& name);
+
+  bool SetPinMux(const std::string& name, const std::string& mux);
+  bool SetPinMuxWithGroup(const std::string& name,
+                          const std::string& mux,
+                          const std::string& group);
+
+  bool RegisterDriver(std::unique_ptr<I2cDriverInfoBase> driver_info);
+
+  std::unique_ptr<I2cDevice> OpenI2cDevice(const std::string& name,
+                                           uint32_t address);
+
+ private:
+  I2cManager();
+
+  std::map<std::string, std::unique_ptr<I2cDriverInfoBase>> driver_infos_;
+  std::map<std::string, I2cDevBus> i2cdev_buses_;
+
+  DISALLOW_COPY_AND_ASSIGN(I2cManager);
+};
+
+}  // namespace android
+
+#endif  // SYSTEM_PERIPHERALMANAGER_DAEMON_I2C_MANAGER_H_
diff --git a/peripheralmanager/daemon/led_driver.h b/peripheralmanager/daemon/led_driver.h
new file mode 100644
index 0000000..15c25e6
--- /dev/null
+++ b/peripheralmanager/daemon/led_driver.h
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef SYSTEM_PERIPHERALMANAGER_DAEMON_LED_DRIVER_H_
+#define SYSTEM_PERIPHERALMANAGER_DAEMON_LED_DRIVER_H_
+
+#include <stdint.h>
+
+#include <memory>
+#include <string>
+
+#include <base/macros.h>
+
+namespace android {
+
+class LedDriverInterface {
+ public:
+  LedDriverInterface() {}
+  virtual ~LedDriverInterface() {}
+
+  // TODO(leecam): Init should have generic params.
+  virtual bool Init(const std::string& name) = 0;
+
+  virtual bool SetBrightness(uint32_t val) = 0;
+
+  virtual bool GetBrightness(uint32_t* val) = 0;
+
+  virtual bool GetMaxBrightness(uint32_t* val) = 0;
+};
+
+class LedDriverInfoBase {
+ public:
+  LedDriverInfoBase() {}
+  virtual ~LedDriverInfoBase() {}
+
+  virtual std::string Compat() = 0;
+  virtual std::unique_ptr<LedDriverInterface> Probe() = 0;
+};
+
+template <class T, class PARAM>
+class LedDriverInfo : public LedDriverInfoBase {
+ public:
+  explicit LedDriverInfo(PARAM param) : param_(param) {}
+  ~LedDriverInfo() override {}
+
+  std::string Compat() override { return T::Compat(); }
+
+  std::unique_ptr<LedDriverInterface> Probe() override {
+    return std::unique_ptr<LedDriverInterface>(new T(param_));
+  }
+
+ private:
+  PARAM param_;
+};
+
+}  // namespace android
+
+#endif  // SYSTEM_PERIPHERALMANAGER_DAEMON_LED_DRIVER_H_
diff --git a/peripheralmanager/daemon/led_driver_sysfs.cc b/peripheralmanager/daemon/led_driver_sysfs.cc
new file mode 100644
index 0000000..0292082
--- /dev/null
+++ b/peripheralmanager/daemon/led_driver_sysfs.cc
@@ -0,0 +1,109 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "led_driver_sysfs.h"
+
+#include <fcntl.h>
+#include <string>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include <base/logging.h>
+
+namespace android {
+namespace {
+
+const char kSysfsLedPathPrefix[] = "/sys/class/leds/";
+const char kMaxBrightnessFilename[] = "max_brightness";
+const char kBrightnessFilename[] = "brightness";
+
+}  // namespace
+
+LedDriverSysfs::LedDriverSysfs(std::string* prefix)
+    : fd_(-1), prefix_(prefix) {}
+
+LedDriverSysfs::~LedDriverSysfs() {
+  if (fd_ >= 0) {
+    close(fd_);
+  }
+}
+
+bool LedDriverSysfs::Init(const std::string& name) {
+  LOG(INFO) << "Opening " << name;
+
+  // If a custom prefix was defined, use it.
+  std::string path = prefix_ ? *prefix_ + name : kSysfsLedPathPrefix + name;
+
+  int fd = open(path.c_str(), O_RDONLY);
+  if (fd < 0) {
+    PLOG(WARNING) << "Failed to open " << path;
+    return false;
+  }
+
+  fd_ = fd;
+  return true;
+}
+
+bool LedDriverSysfs::SetBrightness(uint32_t val) {
+  return WriteToFile(kBrightnessFilename, std::to_string(val));
+}
+
+bool LedDriverSysfs::GetBrightness(uint32_t* val) {
+  std::string str_val;
+  if (!ReadFromFile(kBrightnessFilename, &str_val))
+    return false;
+  *val = std::stoi(str_val);
+  return true;
+}
+
+bool LedDriverSysfs::GetMaxBrightness(uint32_t* val) {
+  std::string str_val;
+  if (!ReadFromFile(kMaxBrightnessFilename, &str_val))
+    return false;
+  *val = std::stoi(str_val);
+  return true;
+}
+
+bool LedDriverSysfs::ReadFromFile(const std::string& file, std::string* value) {
+  int fd = openat(fd_, file.c_str(), O_RDONLY);
+  if (fd < 0)
+    return false;
+  char tmp_buf[16] = "";
+  ssize_t bytes = read(fd, tmp_buf, sizeof(tmp_buf));
+  close(fd);
+  if (bytes < 0)
+    return false;
+  value->assign(tmp_buf, bytes);
+  return true;
+}
+
+bool LedDriverSysfs::WriteToFile(const std::string& file,
+                                 const std::string& value) {
+  int fd = openat(fd_, file.c_str(), O_RDWR);
+  if (fd < 0)
+    return false;
+
+  ssize_t bytes = write(fd, value.c_str(), value.size());
+  close(fd);
+  if (bytes < 0)
+    return false;
+  if ((size_t)bytes != value.size())
+    return false;
+  return true;
+}
+
+}  // namespace android
diff --git a/peripheralmanager/daemon/led_driver_sysfs.h b/peripheralmanager/daemon/led_driver_sysfs.h
new file mode 100644
index 0000000..c4c46fc
--- /dev/null
+++ b/peripheralmanager/daemon/led_driver_sysfs.h
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef SYSTEM_PERIPHERALMANAGER_DAEMON_LED_DRIVER_SYSFS_H_
+#define SYSTEM_PERIPHERALMANAGER_DAEMON_LED_DRIVER_SYSFS_H_
+
+#include <stdint.h>
+
+#include <base/macros.h>
+
+#include "led_driver.h"
+
+namespace android {
+
+class LedDriverSysfs : public LedDriverInterface {
+ public:
+  explicit LedDriverSysfs(std::string* prefix);
+  ~LedDriverSysfs();
+
+  static std::string Compat() { return "LEDSYSFS"; }
+
+  bool Init(const std::string& name) override;
+  bool SetBrightness(uint32_t val) override;
+  bool GetBrightness(uint32_t* val) override;
+  bool GetMaxBrightness(uint32_t* val) override;
+
+ private:
+  bool ReadFromFile(const std::string& file, std::string* value);
+  bool WriteToFile(const std::string& file, const std::string& value);
+
+  int fd_;
+
+  // Used for unit test only.
+  // Ownership is in the test.
+  std::string* prefix_;
+
+  DISALLOW_COPY_AND_ASSIGN(LedDriverSysfs);
+};
+
+}  // namespace android
+
+#endif  // SYSTEM_PERIPHERALMANAGER_DAEMON_LED_DRIVER_SYSFS_H_
diff --git a/peripheralmanager/daemon/led_manager.cc b/peripheralmanager/daemon/led_manager.cc
new file mode 100644
index 0000000..72e200f
--- /dev/null
+++ b/peripheralmanager/daemon/led_manager.cc
@@ -0,0 +1,107 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "led_manager.h"
+
+#include <base/logging.h>
+
+namespace android {
+
+std::unique_ptr<LedManager> g_led_manager;
+
+LedManager::LedManager() {}
+
+LedManager::~LedManager() {}
+
+// static
+LedManager* LedManager::GetLedManager() {
+  if (!g_led_manager) {
+    g_led_manager.reset(new LedManager());
+  }
+  return g_led_manager.get();
+}
+
+// static
+void LedManager::ResetLedManager() {
+  g_led_manager.reset();
+}
+
+bool LedManager::RegisterDriver(
+    std::unique_ptr<LedDriverInfoBase> driver_info) {
+  std::string key = driver_info->Compat();
+  driver_infos_[key] = std::move(driver_info);
+  return true;
+}
+
+bool LedManager::RegisterLedSysfs(const std::string& name,
+                                  const std::string& led_name) {
+  if (leds_.count(name))
+    return false;
+  leds_[name].name = led_name;
+  return true;
+}
+
+std::unique_ptr<Led> LedManager::OpenLed(const std::string& name) {
+  auto led_it = leds_.find(name);
+  if (led_it == leds_.end()) {
+    LOG(WARNING) << "LedManager: Led not found. " << name;
+    return nullptr;
+  }
+
+  // Check its not alread in use
+  if (led_it->second.driver_) {
+    LOG(WARNING) << "LedManager: Led in use. " << name;
+    return nullptr;
+  }
+
+  // Find a driver.
+  auto driver_info_it = driver_infos_.find("LEDSYSFS");
+
+  // Fail if there is no driver.
+  if (driver_info_it == driver_infos_.end()) {
+    LOG(WARNING) << "LedManager: Failed to find driver " << name;
+    return nullptr;
+  }
+
+  std::unique_ptr<LedDriverInterface> driver(driver_info_it->second->Probe());
+
+  // Set pin mux
+  if (!led_it->second.mux.empty()) {
+    // TODO(leecam): Enable pin muxing
+  }
+
+  if (!driver->Init(led_it->second.name)) {
+    LOG(WARNING) << "LedManager: Failed to init driver " << name;
+    return nullptr;
+  }
+
+  led_it->second.driver_ = std::move(driver);
+
+  return std::unique_ptr<Led>(new Led(&(led_it->second)));
+}
+
+std::vector<std::string> LedManager::GetLeds() {
+  std::vector<std::string> leds;
+  for (auto& i : leds_)
+    leds.push_back(i.first);
+  return leds;
+}
+
+bool LedManager::HasLed(const std::string& name) {
+  return leds_.count(name);
+}
+
+}  // namespace android
diff --git a/peripheralmanager/daemon/led_manager.h b/peripheralmanager/daemon/led_manager.h
new file mode 100644
index 0000000..b6c93f9
--- /dev/null
+++ b/peripheralmanager/daemon/led_manager.h
@@ -0,0 +1,95 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef SYSTEM_PERIPHERALMANAGER_DAEMON_LED_MANAGER_H_
+#define SYSTEM_PERIPHERALMANAGER_DAEMON_LED_MANAGER_H_
+
+#include <stdint.h>
+
+#include <map>
+#include <memory>
+#include <string>
+#include <vector>
+
+#include <base/macros.h>
+
+#include "led_driver.h"
+#include "pin_mux_manager.h"
+
+namespace android {
+
+struct LedSysfs {
+  std::string name;
+  std::string mux;
+  std::unique_ptr<LedDriverInterface> driver_;
+};
+
+class Led {
+ public:
+  explicit Led(LedSysfs* led) : led_(led) {}
+  ~Led() {
+    if (!led_->mux.empty()) {
+      // TODO(leecam): Set up pin muxing
+    }
+    led_->driver_.reset();
+  }
+
+  bool SetBrightness(uint32_t val) { return led_->driver_->SetBrightness(val); }
+
+  bool GetBrightness(uint32_t* val) {
+    return led_->driver_->GetBrightness(val);
+  }
+
+  bool GetMaxBrightness(uint32_t* val) {
+    return led_->driver_->GetMaxBrightness(val);
+  }
+
+ private:
+  LedSysfs* led_;
+};
+
+class LedManager {
+ public:
+  friend class LedManagerTest;
+  ~LedManager();
+
+  // Get the singleton.
+  static LedManager* GetLedManager();
+  static void ResetLedManager();
+
+  // Used by the BSP to tell PMan of an sysfs led.
+  bool RegisterLedSysfs(const std::string& name, const std::string& led_name);
+  bool SetPinMux(const std::string& name, const std::string& mux);
+
+  std::vector<std::string> GetLeds();
+  bool HasLed(const std::string& name);
+
+  bool RegisterDriver(std::unique_ptr<LedDriverInfoBase> driver_info);
+
+  std::unique_ptr<Led> OpenLed(const std::string& name);
+
+ private:
+  LedManager();
+
+  std::map<std::string, std::unique_ptr<LedDriverInfoBase>> driver_infos_;
+  std::map<std::string, LedSysfs> leds_;
+
+  DISALLOW_COPY_AND_ASSIGN(LedManager);
+};
+
+}  // namespace android
+
+#endif  // SYSTEM_PERIPHERALMANAGER_DAEMON_LED_MANAGER_H_
diff --git a/peripheralmanager/daemon/main.cc b/peripheralmanager/daemon/main.cc
new file mode 100644
index 0000000..461f401
--- /dev/null
+++ b/peripheralmanager/daemon/main.cc
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <sysexits.h>
+
+#include <base/logging.h>
+#include <base/macros.h>
+#include <binderwrapper/binder_wrapper.h>
+#include <brillo/binder_watcher.h>
+#include <brillo/daemons/daemon.h>
+#include <brillo/flag_helper.h>
+
+#include "peripheral_manager.h"
+
+namespace {
+
+class PeripheralManagerDaemon : public brillo::Daemon {
+ public:
+  PeripheralManagerDaemon() {};
+
+  ~PeripheralManagerDaemon() override = default;
+
+ private:
+  // brillo::Daemon:
+  int OnInit() override {
+    int result = brillo::Daemon::OnInit();
+    if (result != EX_OK)
+      return result;
+
+    android::BinderWrapper::Create();
+    if (!binder_watcher_.Init())
+      return EX_OSERR;
+    if (!peripheral_manager_.Init())
+      return EX_OSERR;
+
+    LOG(INFO) << "Initialization complete";
+    return EX_OK;
+  }
+
+  brillo::BinderWatcher binder_watcher_;
+  android::PeripheralManager peripheral_manager_;
+
+  DISALLOW_COPY_AND_ASSIGN(PeripheralManagerDaemon);
+};
+
+}  // namespace
+
+int main(int argc, char *argv[]) {
+  brillo::FlagHelper::Init(argc, argv, "Peripheral management daemon");
+  logging::InitLogging(logging::LoggingSettings());
+  return PeripheralManagerDaemon().Run();
+}
diff --git a/peripheralmanager/daemon/peripheral_manager.cc b/peripheralmanager/daemon/peripheral_manager.cc
new file mode 100644
index 0000000..ba8c6aa
--- /dev/null
+++ b/peripheralmanager/daemon/peripheral_manager.cc
@@ -0,0 +1,224 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "peripheral_manager.h"
+
+#include <base/logging.h>
+#include <binderwrapper/binder_wrapper.h>
+#include <binderwrapper/stub_binder_wrapper.h>
+#include <hardware/hardware.h>
+#include <hardware/peripheral_io.h>
+
+#include "gpio_driver_sysfs.h"
+#include "gpio_manager.h"
+#include "i2c_driver_i2cdev.h"
+#include "i2c_manager.h"
+#include "led_driver_sysfs.h"
+#include "led_manager.h"
+#include "pin_mux_manager.h"
+#include "spi_driver_spidev.h"
+#include "uart_driver_sysfs.h"
+#include "uart_manager.h"
+
+namespace android {
+namespace {
+
+// Gpio callbacks
+static int RegisterGpioSysfs(const char* name, uint32_t index) {
+  return GpioManager::GetGpioManager()->RegisterGpioSysfs(name, index);
+}
+
+static int SetGpioPinMux(const char* name, const char* source) {
+  return GpioManager::GetGpioManager()->SetPinMux(name, source);
+}
+
+// Spi callbacks
+static int RegisterSpiDevBus(const char* name, uint32_t bus, uint32_t cs) {
+  return SpiManager::GetSpiManager()->RegisterSpiDevBus(name, bus, cs);
+}
+
+static int SetSpiPinMux(const char* name, const char* source) {
+  return SpiManager::GetSpiManager()->SetPinMux(name, source);
+}
+
+// Led callbacks
+static int RegisterLedSysfs(const char* name, const char* sysfs_name) {
+  return LedManager::GetLedManager()->RegisterLedSysfs(name, sysfs_name);
+}
+
+// Uart callbacks
+static int RegisterUartBus(const char* name, const char* dev_name) {
+  return UartManager::GetManager()->RegisterUartDevice(name, dev_name);
+}
+
+static int SetUartPinMux(const char* name, const char* source) {
+  return UartManager::GetManager()->SetPinMux(name, source);
+}
+
+// I2c callbacks
+static int RegisterI2cDevBus(const char* name, uint32_t bus) {
+  return I2cManager::GetI2cManager()->RegisterI2cDevBus(name, bus);
+}
+
+static int SetI2cPinMux(const char* name, const char* source) {
+  return I2cManager::GetI2cManager()->SetPinMux(name, source);
+}
+
+// Pin Mux callbacks.
+static int RegisterPin(const char* name,
+                       int gpio,
+                       pin_mux_callbacks callbacks) {
+  return PinMuxManager::GetPinMuxManager()->RegisterPin(name, gpio, callbacks);
+}
+
+static int RegisterPinGroup(const char* name, char** pins, size_t nr_pins) {
+  std::set<std::string> pins_set;
+  for (size_t i = 0; i < nr_pins; i++)
+    pins_set.emplace(pins[i]);
+  return PinMuxManager::GetPinMuxManager()->RegisterPinGroup(name, pins_set);
+}
+
+static int RegisterSource(const char* name, char** groups, size_t nr_groups) {
+  std::set<std::string> groups_set;
+  for (size_t i = 0; i < nr_groups; i++)
+    groups_set.emplace(groups[i]);
+  return PinMuxManager::GetPinMuxManager()->RegisterSource(name, groups_set);
+}
+
+static int RegisterSimpleSource(const char* name,
+                                const char** pins,
+                                size_t nr_pins) {
+  std::set<std::string> pins_set;
+  for (size_t i = 0; i < nr_pins; i++)
+    pins_set.emplace(pins[i]);
+  return PinMuxManager::GetPinMuxManager()->RegisterSimpleSource(name,
+                                                                 pins_set);
+}
+
+}  // namespace
+
+PeripheralManager::PeripheralManager() {}
+
+PeripheralManager::~PeripheralManager() = default;
+
+bool PeripheralManager::Init() {
+  if (!RegisterDrivers())
+    return false;
+
+  if (!InitHal())
+    return false;
+
+  String8 interface_desc(getInterfaceDescriptor());
+  return BinderWrapper::Get()->RegisterService(interface_desc.string(), this);
+}
+
+Status PeripheralManager::GetClient(const sp<IBinder>& lifeline,
+                                    sp<os::IPeripheralManagerClient>* client) {
+  sp<PeripheralManagerClient> c = new PeripheralManagerClient;
+  *client = c;
+
+  lifeline->linkToDeath(this);
+  mapping_.emplace(lifeline.get(), c);
+  VLOG(1) << "client connecting " << mapping_.size();
+
+  return Status::ok();
+}
+
+void PeripheralManager::binderDied(const wp<IBinder>& who) {
+  mapping_.erase(who.unsafe_get());
+  VLOG(1) << "client disconnecting " << mapping_.size();
+}
+
+bool PeripheralManager::RegisterDrivers() {
+  if (!SpiManager::GetSpiManager()->RegisterDriver(
+          std::unique_ptr<SpiDriverInfoBase>(
+              new SpiDriverInfo<SpiDriverSpiDev, CharDeviceFactory*>(
+                  nullptr)))) {
+    LOG(ERROR) << "Failed to load driver: SpiDriverSpiDev";
+    return false;
+  }
+  if (!I2cManager::GetI2cManager()->RegisterDriver(
+          std::unique_ptr<I2cDriverInfoBase>(
+              new I2cDriverInfo<I2cDriverI2cDev, CharDeviceFactory*>(
+                  nullptr)))) {
+    LOG(ERROR) << "Failed to load driver: I2cDriverI2cDev";
+    return false;
+  }
+  if (!GpioManager::GetGpioManager()->RegisterDriver(
+          std::unique_ptr<GpioDriverInfoBase>(
+              new GpioDriverInfo<GpioDriverSysfs, void*>(nullptr)))) {
+    LOG(ERROR) << "Failed to load driver: GpioDriverSysfs";
+    return false;
+  }
+  if (!LedManager::GetLedManager()->RegisterDriver(
+          std::unique_ptr<LedDriverInfoBase>(
+              new LedDriverInfo<LedDriverSysfs, std::string*>(nullptr)))) {
+    LOG(ERROR) << "Failed to load driver: LedDriverSysfs";
+    return false;
+  }
+  if (!UartManager::GetManager()->RegisterDriver(
+          std::unique_ptr<UartDriverInfoBase>(
+              new UartDriverInfo<UartDriverSysfs, CharDeviceFactory*>(
+                  nullptr)))) {
+    LOG(ERROR) << "Failed to load driver: UartDriverSysfs";
+    return false;
+  }
+  return true;
+}
+
+bool PeripheralManager::InitHal() {
+  const hw_module_t* module = nullptr;
+  if (hw_get_module(PERIPHERAL_IO_HARDWARE_MODULE_ID, &module) != 0) {
+    LOG(ERROR) << "Failed to load HAL" << module;
+    return true;
+  }
+
+  const peripheral_io_module_t* peripheral_module =
+      reinterpret_cast<const peripheral_io_module_t*>(module);
+
+  struct peripheral_registration_cb_t callbacks = {
+      // Gpio
+      .register_gpio_sysfs = RegisterGpioSysfs,
+      .set_gpio_pin_mux = SetGpioPinMux,
+
+      // Spi
+      .register_spi_dev_bus = RegisterSpiDevBus,
+      .set_spi_pin_mux = SetSpiPinMux,
+
+      // Led
+      .register_led_sysfs = RegisterLedSysfs,
+
+      // Uart
+      .register_uart_bus = RegisterUartBus,
+      .set_uart_pin_mux = SetUartPinMux,
+
+      // I2c
+      .register_i2c_dev_bus = RegisterI2cDevBus,
+      .set_i2c_pin_mux = SetI2cPinMux,
+
+      // Pin Mux
+      .register_pin = RegisterPin,
+      .register_pin_group = RegisterPinGroup,
+      .register_source = RegisterSource,
+      .register_simple_source = RegisterSimpleSource,
+  };
+
+  peripheral_module->register_devices(peripheral_module, &callbacks);
+
+  return true;
+}
+
+}  // namespace android
diff --git a/peripheralmanager/daemon/peripheral_manager.h b/peripheralmanager/daemon/peripheral_manager.h
new file mode 100644
index 0000000..8b5568f
--- /dev/null
+++ b/peripheralmanager/daemon/peripheral_manager.h
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef SYSTEM_PERIPHERALMANAGER_DAEMON_PERIPHERAL_MANAGER_H_
+#define SYSTEM_PERIPHERALMANAGER_DAEMON_PERIPHERAL_MANAGER_H_
+
+#include <map>
+
+#include <base/macros.h>
+
+#include <android/os/BnPeripheralManager.h>
+
+#include "peripheral_manager_client.h"
+
+using android::binder::Status;
+using android::os::BnPeripheralManager;
+
+namespace android {
+
+class PeripheralManager : public BnPeripheralManager,
+                          public BnPeripheralManager::DeathRecipient {
+ public:
+  PeripheralManager();
+  ~PeripheralManager();
+
+  bool Init();
+
+  // IPeripheralManager Interface
+  Status GetClient(const sp<IBinder>& lifeline,
+                   sp<os::IPeripheralManagerClient>* _aidl_return);
+
+  void binderDied(const wp<IBinder>& who) override;
+
+ private:
+  bool InitHal();
+  bool RegisterDrivers();
+
+  std::map<IBinder*, sp<PeripheralManagerClient>> mapping_;
+
+  DISALLOW_COPY_AND_ASSIGN(PeripheralManager);
+};
+
+}  // namespace android
+
+#endif  // SYSTEM_PERIPHERALMANAGER_DAEMON_PERIPHERAL_MANAGER_H_
diff --git a/peripheralmanager/daemon/peripheral_manager_client.cc b/peripheralmanager/daemon/peripheral_manager_client.cc
new file mode 100644
index 0000000..8dc30ea
--- /dev/null
+++ b/peripheralmanager/daemon/peripheral_manager_client.cc
@@ -0,0 +1,566 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "peripheral_manager_client.h"
+
+#include <base/logging.h>
+
+namespace android {
+
+PeripheralManagerClient::PeripheralManagerClient() {}
+PeripheralManagerClient::~PeripheralManagerClient() {}
+
+Status PeripheralManagerClient::ListGpio(std::vector<std::string>* gpios) {
+  *gpios = GpioManager::GetGpioManager()->GetGpioPins();
+  return Status::ok();
+}
+
+Status PeripheralManagerClient::OpenGpio(const std::string& name) {
+  if (!GpioManager::GetGpioManager()->HasGpio(name))
+    return Status::fromServiceSpecificError(ENODEV);
+
+  auto gpio = GpioManager::GetGpioManager()->OpenGpioPin(name);
+  if (!gpio) {
+    LOG(ERROR) << "Failed to open GPIO " << name;
+    return Status::fromServiceSpecificError(EBUSY);
+  }
+
+  gpios_.emplace(name, std::move(gpio));
+  return Status::ok();
+}
+
+Status PeripheralManagerClient::ReleaseGpio(const std::string& name) {
+  gpios_.erase(name);
+  return Status::ok();
+}
+
+Status PeripheralManagerClient::SetGpioEdge(const std::string& name, int type) {
+  if (!gpios_.count(name))
+    return Status::fromServiceSpecificError(EPERM);
+
+  if (gpios_.find(name)->second->SetEdgeType(GpioEdgeType(type)))
+    return Status::ok();
+
+  return Status::fromServiceSpecificError(EREMOTEIO);
+}
+
+Status PeripheralManagerClient::SetGpioActiveType(const std::string& name,
+                                                  int type) {
+  if (!gpios_.count(name))
+    return Status::fromServiceSpecificError(EPERM);
+
+  if (gpios_.find(name)->second->SetActiveType(GpioActiveType(type)))
+    return Status::ok();
+
+  return Status::fromServiceSpecificError(EREMOTEIO);
+}
+
+Status PeripheralManagerClient::SetGpioDirection(const std::string& name,
+                                                 int direction) {
+  if (!gpios_.count(name))
+    return Status::fromServiceSpecificError(EPERM);
+
+  if (gpios_.find(name)->second->SetDirection(GpioDirection(direction)))
+    return Status::ok();
+
+  return Status::fromServiceSpecificError(EREMOTEIO);
+}
+
+Status PeripheralManagerClient::SetGpioValue(const std::string& name,
+                                             bool value) {
+  if (!gpios_.count(name))
+    return Status::fromServiceSpecificError(EPERM);
+
+  if (gpios_.find(name)->second->SetValue(value))
+    return Status::ok();
+
+  return Status::fromServiceSpecificError(EREMOTEIO);
+}
+
+Status PeripheralManagerClient::GetGpioValue(const std::string& name,
+                                             bool* value) {
+  if (!gpios_.count(name))
+    return Status::fromServiceSpecificError(EPERM);
+
+  if (gpios_.find(name)->second->GetValue(value))
+    return Status::ok();
+
+  return Status::fromServiceSpecificError(EREMOTEIO);
+}
+
+Status PeripheralManagerClient::GetGpioPollingFd(
+    const std::string& name,
+    ::android::base::unique_fd* fd) {
+  if (!gpios_.count(name))
+    return Status::fromServiceSpecificError(EPERM);
+
+  if (gpios_.find(name)->second->GetPollingFd(fd))
+    return Status::ok();
+
+  return Status::fromServiceSpecificError(EREMOTEIO);
+}
+
+Status PeripheralManagerClient::ListSpiBuses(std::vector<std::string>* buses) {
+  *buses = SpiManager::GetSpiManager()->GetSpiDevBuses();
+  return Status::ok();
+}
+
+Status PeripheralManagerClient::OpenSpiDevice(const std::string& name) {
+  if (!SpiManager::GetSpiManager()->HasSpiDevBus(name))
+    return Status::fromServiceSpecificError(ENODEV);
+
+  std::unique_ptr<SpiDevice> device =
+      SpiManager::GetSpiManager()->OpenSpiDevice(name);
+
+  if (!device) {
+    LOG(ERROR) << "Failed to open device " << name;
+    return Status::fromServiceSpecificError(EBUSY);
+  }
+
+  spi_devices_.emplace(name, std::move(device));
+  return Status::ok();
+}
+
+Status PeripheralManagerClient::ReleaseSpiDevice(const std::string& name) {
+  if (!spi_devices_.count(name))
+    return Status::fromServiceSpecificError(EPERM);
+
+  spi_devices_.erase(name);
+  return Status::ok();
+}
+
+Status PeripheralManagerClient::SpiDeviceWriteByte(const std::string& name,
+                                                   int8_t byte) {
+  if (!spi_devices_.count(name))
+    return Status::fromServiceSpecificError(EPERM);
+
+  if (spi_devices_.find(name)->second->WriteByte(byte))
+    return Status::ok();
+
+  return Status::fromServiceSpecificError(EREMOTEIO);
+}
+
+Status PeripheralManagerClient::SpiDeviceWriteBuffer(
+    const std::string& name,
+    const std::vector<uint8_t>& buffer) {
+  if (!spi_devices_.count(name))
+    return Status::fromServiceSpecificError(EPERM);
+
+  if (spi_devices_.find(name)->second->WriteBuffer(buffer.data(),
+                                                   buffer.size()))
+    return Status::ok();
+
+  return Status::fromServiceSpecificError(EREMOTEIO);
+}
+
+Status PeripheralManagerClient::SpiDeviceTransfer(
+    const std::string& name,
+    const std::unique_ptr<std::vector<uint8_t>>& tx_data,
+    std::unique_ptr<std::vector<uint8_t>>* rx_data,
+    int size) {
+  if (!spi_devices_.count(name))
+    return Status::fromServiceSpecificError(EPERM);
+
+  if (!rx_data) {
+    if (spi_devices_.find(name)->second->Transfer(tx_data->data(), nullptr,
+                                                  size)) {
+      return Status::ok();
+    }
+  } else {
+    rx_data->reset(new std::vector<uint8_t>(size));
+    if (spi_devices_.find(name)->second->Transfer(tx_data->data(),
+                                                  (*rx_data)->data(), size)) {
+      return Status::ok();
+    }
+  }
+
+  return Status::fromServiceSpecificError(EREMOTEIO);
+}
+
+Status PeripheralManagerClient::SpiDeviceSetMode(const std::string& name,
+                                                 int mode) {
+  if (!spi_devices_.count(name))
+    return Status::fromServiceSpecificError(EPERM);
+
+  if (spi_devices_.find(name)->second->SetMode(SpiMode(mode)))
+    return Status::ok();
+
+  return Status::fromServiceSpecificError(EREMOTEIO);
+}
+
+Status PeripheralManagerClient::SpiDeviceSetFrequency(const std::string& name,
+                                                      int frequency_hz) {
+  if (!spi_devices_.count(name))
+    return Status::fromServiceSpecificError(EPERM);
+
+  if (frequency_hz > 0 &&
+      spi_devices_.find(name)->second->SetFrequency(frequency_hz))
+    return Status::ok();
+
+  return Status::fromServiceSpecificError(EREMOTEIO);
+}
+
+Status PeripheralManagerClient::SpiDeviceSetBitJustification(
+    const std::string& name,
+    bool lsb_first) {
+  if (!spi_devices_.count(name))
+    return Status::fromServiceSpecificError(EPERM);
+
+  if (spi_devices_.find(name)->second->SetBitJustification(lsb_first))
+    return Status::ok();
+
+  return Status::fromServiceSpecificError(EREMOTEIO);
+}
+
+Status PeripheralManagerClient::SpiDeviceSetBitsPerWord(const std::string& name,
+                                                        int nbits) {
+  if (!spi_devices_.count(name))
+    return Status::fromServiceSpecificError(EPERM);
+
+  if (spi_devices_.find(name)->second->SetBitsPerWord(nbits))
+    return Status::ok();
+
+  return Status::fromServiceSpecificError(EREMOTEIO);
+}
+
+Status PeripheralManagerClient::SpiDeviceSetDelay(const std::string& name,
+                                                  int delay_usecs) {
+  if (!spi_devices_.count(name))
+    return Status::fromServiceSpecificError(EPERM);
+
+  // |delay_usecs| must be positive and fit in an unsigned 16 bit.
+  if (delay_usecs < 0 || delay_usecs > INT16_MAX)
+    return Status::fromServiceSpecificError(EINVAL);
+
+  if (spi_devices_.find(name)->second->SetDelay(
+          static_cast<uint16_t>(delay_usecs)))
+    return Status::ok();
+
+  return Status::fromServiceSpecificError(EREMOTEIO);
+}
+
+Status PeripheralManagerClient::ListLeds(std::vector<std::string>* leds) {
+  *leds = LedManager::GetLedManager()->GetLeds();
+  return Status::ok();
+}
+
+Status PeripheralManagerClient::OpenLed(const std::string& name) {
+  if (!LedManager::GetLedManager()->HasLed(name)) {
+    return Status::fromServiceSpecificError(ENODEV);
+  }
+  auto led = LedManager::GetLedManager()->OpenLed(name);
+  if (!led) {
+    LOG(ERROR) << "Failed to open LED " << name;
+    return Status::fromServiceSpecificError(EBUSY);
+  }
+
+  leds_.emplace(name, std::move(led));
+  return Status::ok();
+}
+
+Status PeripheralManagerClient::ReleaseLed(const std::string& name) {
+  leds_.erase(name);
+  return Status::ok();
+}
+
+Status PeripheralManagerClient::LedGetBrightness(const std::string& name,
+                                                 int* brightness) {
+  if (!leds_.count(name))
+    return Status::fromServiceSpecificError(EPERM);
+
+  uint32_t temp;
+  if (leds_.find(name)->second->GetBrightness(&temp)) {
+    *brightness = temp;
+    return Status::ok();
+  }
+
+  return Status::fromServiceSpecificError(EREMOTEIO);
+}
+
+Status PeripheralManagerClient::LedGetMaxBrightness(const std::string& name,
+                                                    int* max_brightness) {
+  if (!leds_.count(name))
+    return Status::fromServiceSpecificError(EPERM);
+
+  uint32_t temp;
+  if (leds_.find(name)->second->GetMaxBrightness(&temp)) {
+    *max_brightness = temp;
+    return Status::ok();
+  }
+
+  return Status::fromServiceSpecificError(EREMOTEIO);
+}
+
+Status PeripheralManagerClient::LedSetBrightness(const std::string& name,
+                                                 int brightness) {
+  if (!leds_.count(name))
+    return Status::fromServiceSpecificError(EPERM);
+
+  if (leds_.find(name)->second->SetBrightness(brightness))
+    return Status::ok();
+
+  return Status::fromServiceSpecificError(EREMOTEIO);
+}
+
+Status PeripheralManagerClient::ListI2cBuses(std::vector<std::string>* buses) {
+  *buses = I2cManager::GetI2cManager()->GetI2cDevBuses();
+
+  return Status::ok();
+}
+
+Status PeripheralManagerClient::OpenI2cDevice(const std::string& name,
+                                              int32_t address) {
+  if (!I2cManager::GetI2cManager()->HasI2cDevBus(name))
+    return Status::fromServiceSpecificError(ENODEV);
+
+  std::unique_ptr<I2cDevice> device =
+      I2cManager::GetI2cManager()->OpenI2cDevice(name, address);
+
+  if (!device) {
+    LOG(ERROR) << "Failed to open device " << name;
+    return Status::fromServiceSpecificError(EBUSY);
+  }
+  std::pair<std::string, uint32_t> i2c_dev(name, address);
+  i2c_devices_.emplace(i2c_dev, std::move(device));
+  return Status::ok();
+}
+
+Status PeripheralManagerClient::ReleaseI2cDevice(const std::string& name,
+                                                 int32_t address) {
+  if (!i2c_devices_.count({name, address}))
+    return Status::fromServiceSpecificError(EPERM);
+
+  i2c_devices_.erase({name, address});
+  return Status::ok();
+}
+
+Status PeripheralManagerClient::I2cRead(const std::string& name,
+                                        int32_t address,
+                                        std::vector<uint8_t>* data,
+                                        int32_t size,
+                                        int32_t* bytes_read) {
+  if (!i2c_devices_.count({name, address}))
+    return Status::fromServiceSpecificError(EPERM);
+
+  if (size < 0) {
+    return Status::fromServiceSpecificError(EINVAL);
+  }
+  data->resize(size);
+
+  uint32_t* nread = reinterpret_cast<uint32_t*>(bytes_read);
+  int32_t ret = i2c_devices_.find({name, address})
+                    ->second->Read(data->data(), data->size(), nread);
+  data->resize(*nread);
+
+  return ret == 0 ? Status::ok() : Status::fromServiceSpecificError(ret);
+}
+
+Status PeripheralManagerClient::I2cReadRegByte(const std::string& name,
+                                               int32_t address,
+                                               int32_t reg,
+                                               int32_t* val) {
+  if (!i2c_devices_.count({name, address}))
+    return Status::fromServiceSpecificError(EPERM);
+
+  uint8_t tmp_val = 0;
+  if (i2c_devices_.find({name, address})->second->ReadRegByte(reg, &tmp_val) ==
+      0) {
+    *val = tmp_val;
+    return Status::ok();
+  }
+
+  return Status::fromServiceSpecificError(EREMOTEIO);
+}
+
+Status PeripheralManagerClient::I2cReadRegWord(const std::string& name,
+                                               int32_t address,
+                                               int32_t reg,
+                                               int32_t* val) {
+  if (!i2c_devices_.count({name, address}))
+    return Status::fromServiceSpecificError(EPERM);
+
+  uint16_t tmp_val = 0;
+  if (i2c_devices_.find({name, address})->second->ReadRegWord(reg, &tmp_val) ==
+      0) {
+    *val = tmp_val;
+    return Status::ok();
+  }
+
+  return Status::fromServiceSpecificError(EREMOTEIO);
+}
+
+Status PeripheralManagerClient::I2cReadRegBuffer(const std::string& name,
+                                                 int32_t address,
+                                                 int32_t reg,
+                                                 std::vector<uint8_t>* data,
+                                                 int32_t size,
+                                                 int32_t* bytes_read) {
+  if (!i2c_devices_.count({name, address}))
+    return Status::fromServiceSpecificError(EPERM);
+
+  if (size < 0) {
+    return Status::fromServiceSpecificError(EINVAL);
+  }
+  data->resize(size);
+
+  uint32_t* nread = reinterpret_cast<uint32_t*>(bytes_read);
+  int32_t ret =
+      i2c_devices_.find({name, address})
+          ->second->ReadRegBuffer(reg, data->data(), data->size(), nread);
+
+  data->resize(*nread);
+  return ret == 0 ? Status::ok() : Status::fromServiceSpecificError(ret);
+}
+
+Status PeripheralManagerClient::I2cWrite(const std::string& name,
+                                         int32_t address,
+                                         const std::vector<uint8_t>& data,
+                                         int32_t* bytes_written) {
+  if (!i2c_devices_.count({name, address}))
+    return Status::fromServiceSpecificError(EPERM);
+
+  int ret = i2c_devices_.find({name, address})
+                ->second->Write(data.data(),
+                                data.size(),
+                                reinterpret_cast<uint32_t*>(bytes_written));
+
+  return ret == 0 ? Status::ok() : Status::fromServiceSpecificError(ret);
+}
+
+Status PeripheralManagerClient::I2cWriteRegByte(const std::string& name,
+                                                int32_t address,
+                                                int32_t reg,
+                                                int8_t val) {
+  if (!i2c_devices_.count({name, address}))
+    return Status::fromServiceSpecificError(EPERM);
+
+  if (i2c_devices_.find({name, address})->second->WriteRegByte(reg, val) == 0) {
+    return Status::ok();
+  }
+
+  return Status::fromServiceSpecificError(EREMOTEIO);
+}
+
+Status PeripheralManagerClient::I2cWriteRegWord(const std::string& name,
+                                                int32_t address,
+                                                int32_t reg,
+                                                int32_t val) {
+  if (!i2c_devices_.count({name, address}))
+    return Status::fromServiceSpecificError(EPERM);
+
+  if (i2c_devices_.find({name, address})->second->WriteRegWord(reg, val) == 0) {
+    return Status::ok();
+  }
+
+  return Status::fromServiceSpecificError(EREMOTEIO);
+}
+
+Status PeripheralManagerClient::I2cWriteRegBuffer(
+    const std::string& name,
+    int32_t address,
+    int32_t reg,
+    const std::vector<uint8_t>& data,
+    int32_t* bytes_written) {
+  if (!i2c_devices_.count({name, address}))
+    return Status::fromServiceSpecificError(EPERM);
+
+  int32_t ret =
+      i2c_devices_.find({name, address})
+          ->second->WriteRegBuffer(reg,
+                                   data.data(),
+                                   data.size(),
+                                   reinterpret_cast<uint32_t*>(bytes_written));
+
+  return ret == 0 ? Status::ok() : Status::fromServiceSpecificError(ret);
+}
+
+Status PeripheralManagerClient::ListUartDevices(
+    std::vector<std::string>* devices) {
+  *devices = UartManager::GetManager()->GetDevicesList();
+  return Status::ok();
+}
+
+Status PeripheralManagerClient::OpenUartDevice(const std::string& name) {
+  if (!UartManager::GetManager()->HasUartDevice(name))
+    return Status::fromServiceSpecificError(ENODEV);
+
+  auto uart_device = UartManager::GetManager()->OpenUartDevice(name);
+  if (!uart_device) {
+    LOG(ERROR) << "Failed to open UART device " << name;
+    return Status::fromServiceSpecificError(EBUSY);
+  }
+
+  uart_devices_.emplace(name, std::move(uart_device));
+  return Status::ok();
+}
+
+Status PeripheralManagerClient::ReleaseUartDevice(const std::string& name) {
+  return uart_devices_.erase(name) ? Status::ok()
+                                   : Status::fromServiceSpecificError(EPERM);
+}
+
+Status PeripheralManagerClient::SetUartDeviceBaudrate(const std::string& name,
+                                                      int32_t baudrate) {
+  auto uart_device = uart_devices_.find(name);
+  if (uart_device == uart_devices_.end())
+    return Status::fromServiceSpecificError(EPERM);
+
+  if (baudrate < 0)
+    return Status::fromServiceSpecificError(EINVAL);
+
+  int ret = uart_device->second->SetBaudrate(static_cast<uint32_t>(baudrate));
+
+  if (ret)
+    return Status::fromServiceSpecificError(ret);
+
+  return Status::ok();
+}
+
+Status PeripheralManagerClient::UartDeviceWrite(
+    const std::string& name,
+    const std::vector<uint8_t>& data,
+    int32_t* bytes_written) {
+  auto uart_device = uart_devices_.find(name);
+  if (uart_device == uart_devices_.end())
+    return Status::fromServiceSpecificError(EPERM);
+
+  int ret = uart_device->second->Write(
+      data, reinterpret_cast<uint32_t*>(bytes_written));
+
+  if (ret)
+    return Status::fromServiceSpecificError(ret);
+
+  return Status::ok();
+}
+
+Status PeripheralManagerClient::UartDeviceRead(const std::string& name,
+                                               std::vector<uint8_t>* data,
+                                               int size,
+                                               int* bytes_read) {
+  auto uart_device = uart_devices_.find(name);
+  if (uart_device == uart_devices_.end())
+    return Status::fromServiceSpecificError(EPERM);
+
+  int ret = uart_device->second->Read(
+      data, size, reinterpret_cast<uint32_t*>(bytes_read));
+
+  if (ret)
+    return Status::fromServiceSpecificError(ret);
+
+  return Status::ok();
+}
+
+}  // namespace android
diff --git a/peripheralmanager/daemon/peripheral_manager_client.h b/peripheralmanager/daemon/peripheral_manager_client.h
new file mode 100644
index 0000000..ee9abe4
--- /dev/null
+++ b/peripheralmanager/daemon/peripheral_manager_client.h
@@ -0,0 +1,197 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef SYSTEM_PERIPHERALMANAGER_DAEMON_PERIPHERAL_MANAGER_CLIENT_H_
+#define SYSTEM_PERIPHERALMANAGER_DAEMON_PERIPHERAL_MANAGER_CLIENT_H_
+
+#include <map>
+#include <memory>
+#include <string>
+
+#include <base/macros.h>
+
+#include <android/os/BnPeripheralManagerClient.h>
+
+#include "gpio_manager.h"
+#include "i2c_manager.h"
+#include "led_manager.h"
+#include "spi_manager.h"
+#include "uart_manager.h"
+
+using android::binder::Status;
+using android::os::BnPeripheralManagerClient;
+
+namespace android {
+
+class PeripheralManagerClient : public BnPeripheralManagerClient {
+ public:
+  PeripheralManagerClient();
+  ~PeripheralManagerClient();
+
+  // Gpio functions.
+  Status ListGpio(std::vector<std::string>* gpios) override;
+
+  Status OpenGpio(const std::string& name) override;
+
+  Status ReleaseGpio(const std::string& name) override;
+
+  Status SetGpioEdge(const std::string& name, int type) override;
+
+  Status SetGpioActiveType(const std::string& name, int type) override;
+
+  Status SetGpioDirection(const std::string& name,
+                          int direction) override;
+
+  Status SetGpioValue(const std::string& name, bool value) override;
+
+  Status GetGpioValue(const std::string& name, bool* value) override;
+
+  Status GetGpioPollingFd(const std::string& name,
+                          ::android::base::unique_fd* fd) override;
+
+  // Spi functions.
+  Status ListSpiBuses(std::vector<std::string>* buses) override;
+
+  Status OpenSpiDevice(const std::string& name) override;
+
+  Status ReleaseSpiDevice(const std::string& name) override;
+
+  Status SpiDeviceWriteByte(const std::string& name,
+                            int8_t byte) override;
+
+  Status SpiDeviceWriteBuffer(
+      const std::string& name,
+      const std::vector<uint8_t>& buffer) override;
+
+  Status SpiDeviceTransfer(
+      const std::string& name,
+      const std::unique_ptr<std::vector<uint8_t>>& tx_data,
+      std::unique_ptr<std::vector<uint8_t>>* rx_data,
+      int len) override;
+
+  Status SpiDeviceSetMode(const std::string& name, int mode) override;
+
+  Status SpiDeviceSetFrequency(const std::string& name,
+                               int frequency_hz) override;
+
+  Status SpiDeviceSetBitJustification(const std::string& name,
+                                      bool lsb_first) override;
+
+  Status SpiDeviceSetBitsPerWord(const std::string& name,
+                                 int nbits) override;
+
+  Status SpiDeviceSetDelay(const std::string& name,
+                           int delay_usecs) override;
+
+  // Led functions.
+  Status ListLeds(std::vector<std::string>* leds) override;
+
+  Status OpenLed(const std::string& name) override;
+
+  Status ReleaseLed(const std::string& name) override;
+
+  Status LedGetBrightness(const std::string& name,
+                          int* brightness) override;
+  Status LedGetMaxBrightness(const std::string& name,
+                             int* max_brightness) override;
+  Status LedSetBrightness(const std::string& name,
+                          int brightness) override;
+
+  // I2c functions.
+  Status ListI2cBuses(std::vector<std::string>* buses) override;
+
+  Status OpenI2cDevice(const std::string& name,
+                       int32_t address) override;
+
+  Status ReleaseI2cDevice(const std::string& name,
+                          int32_t address) override;
+
+  Status I2cRead(const std::string& name,
+                 int32_t address,
+                 std::vector<uint8_t>* data,
+                 int32_t size,
+                 int32_t* bytes_read) override;
+
+  Status I2cReadRegByte(const std::string& name,
+                        int32_t address,
+                        int32_t reg,
+                        int32_t* val) override;
+
+  Status I2cReadRegWord(const std::string& name,
+                        int32_t address,
+                        int32_t reg,
+                        int32_t* val) override;
+
+  Status I2cReadRegBuffer(const std::string& name,
+                          int32_t address,
+                          int32_t reg,
+                          std::vector<uint8_t>* data,
+                          int32_t size,
+                          int32_t* bytes_read) override;
+
+  Status I2cWrite(const std::string& name,
+                  int32_t address,
+                  const std::vector<uint8_t>& data,
+                  int32_t* bytes_written) override;
+
+  Status I2cWriteRegByte(const std::string& name,
+                         int32_t address,
+                         int32_t reg,
+                         int8_t val) override;
+
+  Status I2cWriteRegWord(const std::string& name,
+                         int32_t address,
+                         int32_t reg,
+                         int32_t val) override;
+
+  Status I2cWriteRegBuffer(const std::string& name,
+                           int32_t address,
+                           int32_t reg,
+                           const std::vector<uint8_t>& data,
+                           int32_t* bytes_written) override;
+
+  // Uart functions.
+  Status ListUartDevices(std::vector<std::string>* devices) override;
+
+  Status OpenUartDevice(const std::string& name) override;
+
+  Status ReleaseUartDevice(const std::string& name) override;
+
+  Status SetUartDeviceBaudrate(const std::string& name,
+                               int32_t baudrate) override;
+
+  Status UartDeviceWrite(const std::string& name,
+                         const std::vector<uint8_t>& data,
+                         int* bytes_written) override;
+
+  Status UartDeviceRead(const std::string& name,
+                        std::vector<uint8_t>* data,
+                        int size,
+                        int* bytes_read) override;
+
+ private:
+  std::map<std::string, std::unique_ptr<GpioPin>> gpios_;
+  std::map<std::pair<std::string, uint32_t>, std::unique_ptr<I2cDevice>>
+      i2c_devices_;
+  std::map<std::string, std::unique_ptr<SpiDevice>> spi_devices_;
+  std::map<std::string, std::unique_ptr<Led>> leds_;
+  std::map<std::string, std::unique_ptr<UartDevice>> uart_devices_;
+  DISALLOW_COPY_AND_ASSIGN(PeripheralManagerClient);
+};
+
+}  // namespace android
+
+#endif  // SYSTEM_PERIPHERALMANAGER_DAEMON_PERIPHERAL_MANAGER_CLIENT_H_
diff --git a/peripheralmanager/daemon/peripheralman.rc b/peripheralmanager/daemon/peripheralman.rc
new file mode 100644
index 0000000..578fac5
--- /dev/null
+++ b/peripheralmanager/daemon/peripheralman.rc
@@ -0,0 +1,4 @@
+service peripheralman /system/bin/peripheralman 
+    class main
+    user root
+    group system
diff --git a/peripheralmanager/daemon/pin_mux_manager.cc b/peripheralmanager/daemon/pin_mux_manager.cc
new file mode 100644
index 0000000..96d7371
--- /dev/null
+++ b/peripheralmanager/daemon/pin_mux_manager.cc
@@ -0,0 +1,167 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "pin_mux_manager.h"
+
+#include <base/logging.h>
+
+namespace android {
+
+std::unique_ptr<PinMuxManager> g_pin_mux_manager;
+
+PinMuxManager::PinMuxManager() {}
+
+PinMuxManager::~PinMuxManager() {}
+
+// static
+PinMuxManager* PinMuxManager::GetPinMuxManager() {
+  if (!g_pin_mux_manager) {
+    g_pin_mux_manager.reset(new PinMuxManager());
+  }
+  return g_pin_mux_manager.get();
+}
+
+bool PinMuxManager::RegisterPin(std::string name,
+                                bool gpio,
+                                pin_mux_callbacks callbacks) {
+  if (pins_.count(name))
+    return false;
+  pins_[name] = {false, gpio, callbacks};
+  return true;
+}
+
+bool PinMuxManager::RegisterPinGroup(std::string name,
+                                     std::set<std::string> pins) {
+  if (groups_.count(name))
+    return false;
+
+  // Check each pin is valid.
+  for (auto& p : pins) {
+    if (!pins_.count(p))
+      return false;
+  }
+  groups_[name] = pins;
+  return true;
+}
+
+bool PinMuxManager::RegisterSource(std::string name,
+                                   std::set<std::string> groups) {
+  if (sources_.count(name))
+    return false;
+
+  // Check each group is valid.
+  for (auto& g : groups) {
+    if (!groups_.count(g))
+      return false;
+  }
+  sources_[name] = groups;
+  return true;
+}
+
+bool PinMuxManager::RegisterSimpleSource(std::string name,
+                                         std::set<std::string> pins) {
+  if (!RegisterPinGroup(name, pins))
+    return false;
+  if (!RegisterSource(name, {name})) {
+    // TODO(leecam): Unregister Group
+    return false;
+  }
+  return true;
+}
+
+bool PinMuxManager::SetSource(std::string name, std::string group) {
+  if (!sources_.count(name))
+    return false;
+
+  if (!sources_[name].count(group))
+    return false;
+
+  // Check to make sure each pin is not in use.
+  for (auto& p : groups_[group]) {
+    if (pins_[p].in_use)
+      return false;
+  }
+
+  // Enable each Pin
+  for (auto& p : groups_[group]) {
+    pins_[p].in_use = true;
+
+    // TODO(leecam): Handle failures here!!!
+    if (pins_[p].callbacks.mux_cb)
+      pins_[p].callbacks.mux_cb(p.c_str(), name.c_str());
+  }
+
+  return true;
+}
+
+void PinMuxManager::ReleaseSource(std::string name, std::string group) {
+  if (!sources_.count(name))
+    return;
+  if (!sources_[name].count(group))
+    return;
+  for (auto& p : groups_[group]) {
+    if (!pins_[p].in_use) {
+      LOG(WARNING) << "Releasig Pin " << p << " that is not in use.";
+    }
+    pins_[p].in_use = false;
+  }
+}
+
+bool PinMuxManager::SetSimpleSource(std::string name) {
+  return SetSource(name, name);
+}
+
+bool PinMuxManager::SetGpio(std::string name) {
+  if (!pins_.count(name)) {
+    LOG(WARNING) << "PinMuxManager: Pin not found " << name;
+    return false;
+  }
+  if (pins_[name].in_use) {
+    LOG(WARNING) << "PinMuxManager: Pin in use " << name;
+    return false;
+  }
+  if (pins_[name].callbacks.mux_cb) {
+    if (!pins_[name].callbacks.mux_cb(name.c_str(), nullptr))
+      return false;
+  }
+  pins_[name].in_use = true;
+  return true;
+}
+
+void PinMuxManager::ReleaseGpio(std::string name) {
+  if (!pins_.count(name))
+    return;
+  pins_[name].in_use = false;
+}
+
+bool PinMuxManager::SetGpioDirection(std::string name, bool output) {
+  if (!pins_.count(name)) {
+    LOG(WARNING) << "SetGpioDirection pin not found " << name;
+    return false;
+  }
+  // Check if not in use - this should maybe be a DCHECK as
+  // it shoudn't be able to happen.
+  if (!pins_[name].in_use) {
+    LOG(WARNING) << "SetGpioDirection not in use " << name;
+    return false;
+  }
+  if (pins_[name].callbacks.direction_cb)
+    return pins_[name].callbacks.direction_cb(name.c_str(), output);
+
+  return true;
+}
+
+}  // namespace android
\ No newline at end of file
diff --git a/peripheralmanager/daemon/pin_mux_manager.h b/peripheralmanager/daemon/pin_mux_manager.h
new file mode 100644
index 0000000..e18ec4a
--- /dev/null
+++ b/peripheralmanager/daemon/pin_mux_manager.h
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef SYSTEM_PERIPHERALMANAGER_DAEMON_PIN_MUX_MANAGER_H_
+#define SYSTEM_PERIPHERALMANAGER_DAEMON_PIN_MUX_MANAGER_H_
+
+#include <stdint.h>
+
+#include <map>
+#include <memory>
+#include <set>
+#include <string>
+#include <vector>
+
+#include <base/macros.h>
+
+#include <hardware/peripheral_io.h>
+
+namespace android {
+
+struct Pin {
+  bool in_use;
+  bool gpio;
+  pin_mux_callbacks callbacks;
+};
+
+class PinMuxManager {
+ public:
+  friend class PinMuxManagerTest;
+  ~PinMuxManager();
+
+  // Get the singleton.
+  static PinMuxManager* GetPinMuxManager();
+
+  // The following Register* functions as used to configure
+  // the pin mux configuation. These are called by the during
+  // BSP setup, using the HAL.
+  bool RegisterPin(std::string name, bool gpio, pin_mux_callbacks callbacks);
+  bool RegisterPinGroup(std::string name, std::set<std::string> pins);
+  bool RegisterSource(std::string name, std::set<std::string> groups);
+  // Helper that registers a source with a default group of the same name.
+  bool RegisterSimpleSource(std::string name, std::set<std::string> pins);
+
+  // Called by the device managers, e.g SpiManager.
+  // These are used to configure the pin muxing at runtime.
+  bool SetSource(std::string name, std::string group);
+  bool SetSimpleSource(std::string name);
+  void ReleaseSource(std::string name, std::string group);
+
+  // Used by the GpioManager to enable Gpio pins.
+  bool SetGpio(std::string name);
+  void ReleaseGpio(std::string name);
+  bool SetGpioDirection(std::string name, bool output);
+
+ private:
+  // Private constuctor as this class is accessed via a singleton.
+  PinMuxManager();
+
+  std::map<std::string, Pin> pins_;
+  std::map<std::string, std::set<std::string>> groups_;
+  std::map<std::string, std::set<std::string>> sources_;
+
+  DISALLOW_COPY_AND_ASSIGN(PinMuxManager);
+};
+
+}  // namespace android
+
+#endif  // SYSTEM_PERIPHERALMANAGER_DAEMON_PIN_MUX_MANAGER_H_
diff --git a/peripheralmanager/daemon/pin_mux_manager_unittest.cc b/peripheralmanager/daemon/pin_mux_manager_unittest.cc
new file mode 100644
index 0000000..aa0073c
--- /dev/null
+++ b/peripheralmanager/daemon/pin_mux_manager_unittest.cc
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdio.h>
+
+#include <gtest/gtest.h>
+
+#include "pin_mux_manager.h"
+
+namespace android {
+
+class PinMuxManagerTest : public ::testing::Test {
+ public:
+  PinMuxManagerTest() {}
+  ~PinMuxManagerTest() = default;
+
+ protected:
+  PinMuxManager manager;
+  pin_mux_callbacks callbacks = {nullptr, nullptr};
+};
+
+TEST_F(PinMuxManagerTest, RegisterPin) {
+  ASSERT_TRUE(manager.RegisterPin("IO1", true, callbacks));
+  ASSERT_TRUE(manager.RegisterPin("IO2", true, callbacks));
+
+  ASSERT_FALSE(manager.RegisterPin("IO1", true, callbacks));
+  ASSERT_FALSE(manager.RegisterPin("IO2", true, callbacks));
+}
+
+TEST_F(PinMuxManagerTest, RegisterGroup) {
+  ASSERT_TRUE(manager.RegisterPin("IO1", true, callbacks));
+  ASSERT_TRUE(manager.RegisterPin("IO2", true, callbacks));
+  ASSERT_TRUE(manager.RegisterPin("IO3", true, callbacks));
+
+  ASSERT_TRUE(manager.RegisterPinGroup("Group1", {"IO1", "IO2", "IO3"}));
+  ASSERT_TRUE(manager.RegisterPinGroup("Group2", {"IO1"}));
+  ASSERT_FALSE(manager.RegisterPinGroup("Group1", {"IO1", "IO2", "IO3"}));
+  ASSERT_FALSE(manager.RegisterPinGroup("Group3", {"IO1", "BAD", "IO3"}));
+}
+
+TEST_F(PinMuxManagerTest, RegisterSource) {
+  ASSERT_TRUE(manager.RegisterPin("IO1", true, callbacks));
+  ASSERT_TRUE(manager.RegisterPin("IO2", true, callbacks));
+  ASSERT_TRUE(manager.RegisterPin("IO3", true, callbacks));
+
+  ASSERT_TRUE(manager.RegisterPinGroup("Group1", {"IO1", "IO2", "IO3"}));
+  ASSERT_TRUE(manager.RegisterPinGroup("Group2", {"IO1"}));
+
+  ASSERT_TRUE(manager.RegisterSource("Source1", {"Group1"}));
+  ASSERT_TRUE(manager.RegisterSource("Source2", {"Group1", "Group2"}));
+
+  ASSERT_FALSE(manager.RegisterSource("Source3", {"Bad"}));
+
+  ASSERT_FALSE(manager.RegisterSource("Source1", {"Group1"}));
+}
+
+TEST_F(PinMuxManagerTest, SetSource) {
+  ASSERT_TRUE(manager.RegisterPin("IO1", true, callbacks));
+  ASSERT_TRUE(manager.RegisterPin("IO2", true, callbacks));
+  ASSERT_TRUE(manager.RegisterPin("IO3", true, callbacks));
+  ASSERT_TRUE(manager.RegisterPin("IO4", true, callbacks));
+
+  ASSERT_TRUE(manager.RegisterPinGroup("Group1", {"IO1", "IO2", "IO3"}));
+  ASSERT_TRUE(manager.RegisterPinGroup("Group2", {"IO4"}));
+
+  ASSERT_TRUE(manager.RegisterSource("Source1", {"Group1", "Group2"}));
+
+  ASSERT_TRUE(manager.SetSource("Source1", "Group1"));
+  ASSERT_TRUE(manager.SetSource("Source1", "Group2"));
+}
+
+// TODO(leecam): Write lots more tetsts :)
+
+}  // namespace android
\ No newline at end of file
diff --git a/peripheralmanager/daemon/spi_driver.h b/peripheralmanager/daemon/spi_driver.h
new file mode 100644
index 0000000..44ecc90
--- /dev/null
+++ b/peripheralmanager/daemon/spi_driver.h
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef SYSTEM_PERIPHERALMANAGER_DAEMON_SPI_DRIVER_H_
+#define SYSTEM_PERIPHERALMANAGER_DAEMON_SPI_DRIVER_H_
+
+#include <stdint.h>
+
+#include <memory>
+#include <string>
+
+#include <base/macros.h>
+
+#include "peripheralmanager/constants.h"
+
+namespace android {
+
+class SpiDriverInterface {
+ public:
+  SpiDriverInterface() {}
+  virtual ~SpiDriverInterface() {}
+
+  // TODO(leecam): Init should have generic params.
+  virtual bool Init(uint32_t bus_id, uint32_t cs) = 0;
+  virtual bool Transfer(const void* tx_data, void* rx_data, size_t len) = 0;
+  virtual bool SetFrequency(uint32_t speed_hz) = 0;
+  virtual bool SetMode(SpiMode mode) = 0;
+  virtual bool SetBitJustification(bool lsb_first) = 0;
+  virtual bool SetBitsPerWord(uint8_t bits_per_word) = 0;
+  virtual bool SetDelay(uint16_t delay_usecs) = 0;
+};
+
+class SpiDriverInfoBase {
+ public:
+  SpiDriverInfoBase() {}
+  virtual ~SpiDriverInfoBase() {}
+
+  virtual std::string Compat() = 0;
+  virtual std::unique_ptr<SpiDriverInterface> Probe() = 0;
+};
+
+template <class T, class PARAM>
+class SpiDriverInfo : public SpiDriverInfoBase {
+ public:
+  explicit SpiDriverInfo(PARAM param) : param_(param) {}
+  ~SpiDriverInfo() override {}
+
+  std::string Compat() override { return T::Compat(); }
+
+  std::unique_ptr<SpiDriverInterface> Probe() override {
+    return std::unique_ptr<SpiDriverInterface>(new T(param_));
+  }
+
+ private:
+  PARAM param_;
+};
+
+}  // namespace android
+
+#endif  // SYSTEM_PERIPHERALMANAGER_DAEMON_SPI_DRIVER_H_
diff --git a/peripheralmanager/daemon/spi_driver_spidev.cc b/peripheralmanager/daemon/spi_driver_spidev.cc
new file mode 100644
index 0000000..2ac4844
--- /dev/null
+++ b/peripheralmanager/daemon/spi_driver_spidev.cc
@@ -0,0 +1,172 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "spi_driver_spidev.h"
+
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include <linux/spi/spidev.h>
+#include <string>
+
+#include <base/logging.h>
+
+namespace android {
+namespace {
+
+const char kSpiDevPath[] = "/dev/spidev";
+
+}  // namespace
+
+SpiDriverSpiDev::SpiDriverSpiDev(CharDeviceFactory* char_device_factory)
+    : fd_(-1), char_device_factory_(char_device_factory) {}
+
+SpiDriverSpiDev::~SpiDriverSpiDev() {
+  if (fd_ >= 0 && char_interface_ != nullptr) {
+    char_interface_->Close(fd_);
+  }
+}
+
+bool SpiDriverSpiDev::Init(uint32_t bus_id, uint32_t cs) {
+  if (fd_ >= 0) {
+    return false;
+  }
+
+  // Get a char device. If char_device_factory_ is set
+  // then this is a unittest and the char device is provided
+  // by the test. Otherwise create a normal CharDevice.
+  if (!char_device_factory_) {
+    char_interface_.reset(new CharDevice());
+  } else {
+    char_interface_ = char_device_factory_->NewCharDevice();
+  }
+
+  std::string path =
+      kSpiDevPath + std::to_string(bus_id) + "." + std::to_string(cs);
+
+  int fd = char_interface_->Open(path.c_str(), O_RDWR);
+  if (fd < 0)
+    return false;
+
+  fd_ = fd;
+
+  // Set the default speed to the max
+  uint32_t max_freq = 0;
+  if (!GetMaxFrequency(&max_freq)) {
+    char_interface_->Close(fd_);
+    fd_ = -1;
+    return false;
+  }
+  speed_hz_ = max_freq;
+
+  // Default to 0 microseconds delay between transfers.
+  delay_usecs_ = 0;
+
+  // Default to 8 bits per word.
+  bits_per_word_ = 8;
+
+  return true;
+}
+
+bool SpiDriverSpiDev::Transfer(const void* tx_data, void* rx_data, size_t len) {
+  struct spi_ioc_transfer msg;
+  memset(&msg, 0, sizeof(msg));
+
+  msg.tx_buf = (unsigned long)tx_data;
+  msg.rx_buf = (unsigned long)rx_data;
+  msg.speed_hz = speed_hz_;
+  msg.bits_per_word = bits_per_word_;
+  msg.delay_usecs = delay_usecs_;
+  msg.len = len;
+
+  if (char_interface_->Ioctl(fd_, SPI_IOC_MESSAGE(1), &msg) < 0) {
+    PLOG(ERROR) << "SPI Transfer IOCTL Failed";
+    return false;
+  }
+  return true;
+}
+
+bool SpiDriverSpiDev::SetFrequency(uint32_t speed_hz) {
+  if (fd_ < 0)
+    return false;
+  // Get the max speed and ensure speed_hz is less than it.
+  uint32_t max_speed = 0;
+  if (!GetMaxFrequency(&max_speed))
+    return false;
+  if (speed_hz > max_speed)
+    speed_hz = max_speed;
+
+  speed_hz_ = speed_hz;
+  return true;
+}
+
+bool SpiDriverSpiDev::GetMaxFrequency(uint32_t* max_freq) {
+  if (char_interface_->Ioctl(fd_, SPI_IOC_RD_MAX_SPEED_HZ, max_freq) < 0) {
+    PLOG(ERROR) << "Failed to get spi max freq";
+    return false;
+  }
+  return true;
+}
+
+bool SpiDriverSpiDev::SetMode(SpiMode mode) {
+  uint8_t k_mode = 0;
+  switch (mode) {
+    case kMode0:
+      k_mode = SPI_MODE_0;
+      break;
+    case kMode1:
+      k_mode = SPI_MODE_1;
+      break;
+    case kMode2:
+      k_mode = SPI_MODE_2;
+      break;
+    case kMode3:
+      k_mode = SPI_MODE_3;
+      break;
+  }
+
+  if (char_interface_->Ioctl(fd_, SPI_IOC_WR_MODE, &k_mode) < 0) {
+    PLOG(ERROR) << "Failed to set mode";
+    return false;
+  }
+
+  return true;
+}
+
+bool SpiDriverSpiDev::SetBitJustification(bool lsb_first) {
+  uint8_t k_lsb_first = lsb_first;
+  if (char_interface_->Ioctl(fd_, SPI_IOC_WR_LSB_FIRST, &k_lsb_first) < 0) {
+    PLOG(ERROR) << "Failed to set bit justifcation";
+    return false;
+  }
+  return true;
+}
+
+bool SpiDriverSpiDev::SetBitsPerWord(uint8_t bits_per_word) {
+  if (char_interface_->Ioctl(fd_, SPI_IOC_WR_BITS_PER_WORD, &bits_per_word) <
+      0) {
+    PLOG(ERROR) << "Failed to set bits per word";
+    return false;
+  }
+  bits_per_word_ = bits_per_word;
+  return true;
+}
+
+bool SpiDriverSpiDev::SetDelay(uint16_t delay_usecs) {
+  delay_usecs_ = delay_usecs;
+  return true;
+}
+
+}  // namespace android
diff --git a/peripheralmanager/daemon/spi_driver_spidev.h b/peripheralmanager/daemon/spi_driver_spidev.h
new file mode 100644
index 0000000..67f3bd5
--- /dev/null
+++ b/peripheralmanager/daemon/spi_driver_spidev.h
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef SYSTEM_PERIPHERALMANAGER_DAEMON_SPI_DRIVER_SPIDEV_H_
+#define SYSTEM_PERIPHERALMANAGER_DAEMON_SPI_DRIVER_SPIDEV_H_
+
+#include <stdint.h>
+
+#include <memory>
+
+#include <base/macros.h>
+
+#include "char_device.h"
+#include "spi_driver.h"
+
+namespace android {
+
+class SpiDriverSpiDev : public SpiDriverInterface {
+ public:
+  explicit SpiDriverSpiDev(CharDeviceFactory* char_device_factory);
+  ~SpiDriverSpiDev();
+
+  static std::string Compat() { return "SPIDEV"; }
+
+  bool Init(uint32_t bus_id, uint32_t cs) override;
+  bool Transfer(const void* tx_data, void* rx_data, size_t len) override;
+  bool SetFrequency(uint32_t speed_hz) override;
+  bool SetMode(SpiMode mode) override;
+  bool SetBitJustification(bool lsb_first) override;
+  bool SetBitsPerWord(uint8_t bits_per_word) override;
+  bool SetDelay(uint16_t delay_usecs) override;
+
+ private:
+  bool GetMaxFrequency(uint32_t* max_freq);
+
+  int fd_;
+  uint32_t bits_per_word_;
+  uint32_t speed_hz_;
+  uint16_t delay_usecs_;
+  std::unique_ptr<CharDeviceInterface> char_interface_;
+
+  // Used for unit testing and is null in production.
+  // Ownership is in the test and outlives this class.
+  CharDeviceFactory* char_device_factory_;
+
+  DISALLOW_COPY_AND_ASSIGN(SpiDriverSpiDev);
+};
+
+}  // namespace android
+
+#endif  // SYSTEM_PERIPHERALMANAGER_DAEMON_SPI_DEVICE_H_
diff --git a/peripheralmanager/daemon/spi_manager.cc b/peripheralmanager/daemon/spi_manager.cc
new file mode 100644
index 0000000..4e11c84
--- /dev/null
+++ b/peripheralmanager/daemon/spi_manager.cc
@@ -0,0 +1,124 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "spi_manager.h"
+
+#include "pin_mux_manager.h"
+
+namespace android {
+
+std::unique_ptr<SpiManager> g_spi_manager;
+
+SpiManager::SpiManager() {}
+
+SpiManager::~SpiManager() {}
+
+// static
+SpiManager* SpiManager::GetSpiManager() {
+  if (!g_spi_manager) {
+    g_spi_manager.reset(new SpiManager());
+  }
+  return g_spi_manager.get();
+}
+
+// static
+void SpiManager::ResetSpiManager() {
+  g_spi_manager.reset();
+}
+
+bool SpiManager::RegisterSpiDevBus(const std::string& name,
+                                   uint32_t bus,
+                                   uint32_t cs) {
+  if (spidev_buses_.count(name))
+    return false;
+  spidev_buses_.emplace(name, SpiDevBus(bus, cs));
+  return true;
+}
+
+std::vector<std::string> SpiManager::GetSpiDevBuses() {
+  std::vector<std::string> buses;
+  for (auto& i : spidev_buses_)
+    buses.push_back(i.first);
+  return buses;
+}
+
+bool SpiManager::HasSpiDevBus(const std::string& name) {
+  return spidev_buses_.count(name);
+}
+
+bool SpiManager::RegisterDriver(
+    std::unique_ptr<SpiDriverInfoBase> driver_info) {
+  std::string key = driver_info->Compat();
+  driver_infos_[key] = std::move(driver_info);
+  return true;
+}
+
+bool SpiManager::SetPinMux(const std::string& name, const std::string& mux) {
+  auto bus_it = spidev_buses_.find(name);
+  if (bus_it == spidev_buses_.end())
+    return false;
+  bus_it->second.mux = mux;
+  bus_it->second.mux_group = mux;
+  return true;
+}
+
+bool SpiManager::SetPinMuxWithGroup(const std::string& name,
+                                    const std::string& mux,
+                                    const std::string& group) {
+  auto bus_it = spidev_buses_.find(name);
+  if (bus_it == spidev_buses_.end())
+    return false;
+  bus_it->second.mux = mux;
+  bus_it->second.mux_group = group;
+  return true;
+}
+
+std::unique_ptr<SpiDevice> SpiManager::OpenSpiDevice(const std::string& name) {
+  // Get the Bus from the BSP.
+  auto bus_it = spidev_buses_.find(name);
+  if (bus_it == spidev_buses_.end())
+    return nullptr;
+
+  // Check its not alread in use
+  if (bus_it->second.driver_) {
+    return nullptr;
+  }
+
+  // Find a driver.
+  // Currently there is only hardcoded support for SPIDEV
+  auto driver_info_it = driver_infos_.find("SPIDEV");
+
+  // Fail if there is no driver.
+  if (driver_info_it == driver_infos_.end())
+    return nullptr;
+
+  std::unique_ptr<SpiDriverInterface> driver(driver_info_it->second->Probe());
+
+  if (!driver->Init(bus_it->second.bus, bus_it->second.cs))
+    return nullptr;
+
+  // Set Pin muxing.
+  if (!bus_it->second.mux.empty()) {
+    PinMuxManager::GetPinMuxManager()->SetSource(bus_it->second.mux,
+                                                 bus_it->second.mux_group);
+  }
+
+  bus_it->second.driver_ = std::move(driver);
+
+  return std::unique_ptr<SpiDevice>(new SpiDevice(&(bus_it->second)));
+}
+
+}  // namespace android
diff --git a/peripheralmanager/daemon/spi_manager.h b/peripheralmanager/daemon/spi_manager.h
new file mode 100644
index 0000000..9ef51e3
--- /dev/null
+++ b/peripheralmanager/daemon/spi_manager.h
@@ -0,0 +1,126 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef SYSTEM_PERIPHERALMANAGER_DAEMON_SPI_MANAGER_H_
+#define SYSTEM_PERIPHERALMANAGER_DAEMON_SPI_MANAGER_H_
+
+#include <stdint.h>
+
+#include <map>
+#include <memory>
+#include <string>
+#include <vector>
+
+#include <base/macros.h>
+
+#include "peripheralmanager/constants.h"
+#include "pin_mux_manager.h"
+#include "spi_driver.h"
+
+namespace android {
+
+struct SpiDevBus {
+  SpiDevBus(uint32_t b, uint32_t c) : bus(b), cs(c) {}
+  uint32_t bus;
+  uint32_t cs;
+  std::string mux;
+  std::string mux_group;
+  std::unique_ptr<SpiDriverInterface> driver_;
+};
+
+class SpiDevice {
+ public:
+  explicit SpiDevice(SpiDevBus* bus) : bus_(bus) {}
+  ~SpiDevice() {
+    if (!bus_->mux.empty()) {
+      PinMuxManager::GetPinMuxManager()->ReleaseSource(bus_->mux,
+                                                       bus_->mux_group);
+    }
+    bus_->driver_.reset();
+  }
+
+  bool WriteByte(uint8_t val) { return Transfer(&val, nullptr, sizeof(val)); }
+
+  bool WriteBuffer(const void* data, size_t len) {
+    return Transfer(data, nullptr, len);
+  }
+
+  bool Transfer(const void* tx_data, void* rx_data, size_t len) {
+    return bus_->driver_->Transfer(tx_data, rx_data, len);
+  }
+
+  bool SetFrequency(uint32_t speed_hz) {
+    return bus_->driver_->SetFrequency(speed_hz);
+  }
+
+  bool SetMode(SpiMode mode) { return bus_->driver_->SetMode(mode); }
+
+  bool SetBitJustification(bool lsb_first) {
+    return bus_->driver_->SetBitJustification(lsb_first);
+  }
+
+  bool SetBitsPerWord(uint8_t bits_per_word) {
+    return bus_->driver_->SetBitsPerWord(bits_per_word);
+  }
+
+  bool SetDelay(uint16_t delay_usecs) {
+    return bus_->driver_->SetDelay(delay_usecs);
+  }
+
+ private:
+  SpiDevBus* bus_;
+};
+
+class SpiManager {
+ public:
+  friend class SpiManagerTest;
+  ~SpiManager();
+
+  // Get the singleton.
+  static SpiManager* GetSpiManager();
+
+  // Reset the Spi manager.
+  static void ResetSpiManager();
+
+  // Used by the BSP to tell PMan of an SPI bus
+  // that can be used by a PMan client.
+  // Will return false if the bus has already been registered.
+  bool RegisterSpiDevBus(const std::string& name, uint32_t bus, uint32_t cs);
+
+  std::vector<std::string> GetSpiDevBuses();
+  bool HasSpiDevBus(const std::string& name);
+
+  bool SetPinMux(const std::string& name, const std::string& mux);
+  bool SetPinMuxWithGroup(const std::string& name,
+                          const std::string& mux,
+                          const std::string& group);
+
+  bool RegisterDriver(std::unique_ptr<SpiDriverInfoBase> driver_info);
+
+  std::unique_ptr<SpiDevice> OpenSpiDevice(const std::string& name);
+
+ private:
+  SpiManager();
+
+  std::map<std::string, std::unique_ptr<SpiDriverInfoBase>> driver_infos_;
+  std::map<std::string, SpiDevBus> spidev_buses_;
+
+  DISALLOW_COPY_AND_ASSIGN(SpiManager);
+};
+
+}  // namespace android
+
+#endif  // SYSTEM_PERIPHERALMANAGER_DAEMON_SPI_MANAGER_H_
diff --git a/peripheralmanager/daemon/spi_manager_unittest.cc b/peripheralmanager/daemon/spi_manager_unittest.cc
new file mode 100644
index 0000000..924b014
--- /dev/null
+++ b/peripheralmanager/daemon/spi_manager_unittest.cc
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdio.h>
+
+#include <gtest/gtest.h>
+
+#include "fake_devices.h"
+#include "spi_manager.h"
+#include "spi_driver_spidev.h"
+
+namespace android {
+
+class SpiManagerTest : public ::testing::Test {
+ public:
+  SpiManagerTest() {
+    manager.RegisterDriver(std::unique_ptr<SpiDriverInfoBase>(
+        new SpiDriverInfo<SpiDriverSpiDev, CharDeviceFactory*>(
+            &device_factory)));
+  }
+  ~SpiManagerTest() = default;
+
+ protected:
+  FakeDeviceFactory device_factory;
+  SpiManager manager;
+};
+
+TEST_F(SpiManagerTest, SimpleRegister) {
+  manager.RegisterSpiDevBus("SPI0_1", 0, 1);
+  std::vector<std::string> busses = manager.GetSpiDevBuses();
+  ASSERT_EQ(1U, busses.size());
+  ASSERT_EQ("SPI0_1", busses[0]);
+}
+
+TEST_F(SpiManagerTest, SimpleOpen) {
+  manager.RegisterSpiDevBus("SPI0_1", 0, 1);
+  std::unique_ptr<SpiDevice> device(manager.OpenSpiDevice("SPI0_1"));
+  ASSERT_NE(nullptr, device);
+  std::unique_ptr<SpiDevice> device2(manager.OpenSpiDevice("SPI0_1"));
+  ASSERT_EQ(nullptr, device2);
+  device.reset();
+  std::unique_ptr<SpiDevice> device3(manager.OpenSpiDevice("SPI0_1"));
+  ASSERT_NE(nullptr, device3);
+}
+
+TEST_F(SpiManagerTest, SetFrequency) {
+  manager.RegisterSpiDevBus("SPI0_1", 0, 1);
+  std::unique_ptr<SpiDevice> device(manager.OpenSpiDevice("SPI0_1"));
+  ASSERT_NE(nullptr, device);
+
+  device->SetFrequency(100);
+}
+
+}  // namespace android
diff --git a/peripheralmanager/daemon/uart_driver.h b/peripheralmanager/daemon/uart_driver.h
new file mode 100644
index 0000000..e8d7ed7
--- /dev/null
+++ b/peripheralmanager/daemon/uart_driver.h
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef SYSTEM_PERIPHERALMANAGER_DAEMON_UART_DRIVER_H_
+#define SYSTEM_PERIPHERALMANAGER_DAEMON_UART_DRIVER_H_
+
+#include <stdint.h>
+
+#include <memory>
+#include <string>
+#include <vector>
+
+#include <base/macros.h>
+
+namespace android {
+
+class UartDriverInterface {
+ public:
+  virtual ~UartDriverInterface() {}
+
+  // TODO(leecam): Init should have generic params.
+  virtual bool Init(const std::string& name) = 0;
+
+  virtual int SetBaudrate(uint32_t baudrate) = 0;
+
+  virtual int Write(const std::vector<uint8_t>& data,
+                    uint32_t* bytes_written) = 0;
+
+  virtual int Read(std::vector<uint8_t>* data,
+                   uint32_t size,
+                   uint32_t* bytes_read) = 0;
+};
+
+class UartDriverInfoBase {
+ public:
+  virtual ~UartDriverInfoBase() {}
+
+  virtual std::string Compat() = 0;
+  virtual std::unique_ptr<UartDriverInterface> Probe() = 0;
+};
+
+template <class T, class PARAM>
+class UartDriverInfo : public UartDriverInfoBase {
+ public:
+  explicit UartDriverInfo(PARAM param) : param_(param) {}
+  ~UartDriverInfo() override {}
+
+  std::string Compat() override { return T::Compat(); }
+
+  std::unique_ptr<UartDriverInterface> Probe() override {
+    return std::unique_ptr<UartDriverInterface>(new T(param_));
+  }
+
+ private:
+  PARAM param_;
+};
+
+}  // namespace android
+
+#endif  // SYSTEM_PERIPHERALMANAGER_DAEMON_UART_DRIVER_H_
diff --git a/peripheralmanager/daemon/uart_driver_sysfs.cc b/peripheralmanager/daemon/uart_driver_sysfs.cc
new file mode 100644
index 0000000..41e3064
--- /dev/null
+++ b/peripheralmanager/daemon/uart_driver_sysfs.cc
@@ -0,0 +1,204 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "uart_driver_sysfs.h"
+
+#include <fcntl.h>
+#include <termios.h>
+
+#include <base/logging.h>
+
+#include "char_device.h"
+
+namespace android {
+
+UartDriverSysfs::UartDriverSysfs(CharDeviceFactory* factory)
+    : char_device_factory_(factory) {}
+
+UartDriverSysfs::~UartDriverSysfs() {}
+
+bool UartDriverSysfs::Init(const std::string& name) {
+  path_ = name;
+
+  // Get a char device. If char_device_factory_ is set
+  // then this is a unittest and the char device is provided
+  // by the test. Otherwise create a normal CharDevice.
+  if (!char_device_factory_) {
+    char_interface_.reset(new CharDevice());
+  } else {
+    char_interface_ = char_device_factory_->NewCharDevice();
+  }
+
+  // Open as non-blocking as we don't want peripheral_manager to block on a
+  // single client read.
+  int fd = char_interface_->Open(path_.c_str(), O_RDWR | O_NONBLOCK);
+  if (fd < 0) {
+    PLOG(WARNING) << "Failed to open " << path_;
+    return false;
+  }
+
+  // Configure the device in raw mode.
+  struct termios config;
+  if (char_interface_->Ioctl(fd, TCGETS, &config)) {
+    PLOG(ERROR) << "Failed to read the tty config";
+    close(fd);
+    return false;
+  }
+  cfmakeraw(&config);
+
+  if (char_interface_->Ioctl(fd, TCSETSF, &config)) {
+    PLOG(ERROR) << "Failed to configure the UART device as Raw.";
+    close(fd);
+    return false;
+  }
+
+  fd_ = fd;
+  return true;
+}
+
+int UartDriverSysfs::SetBaudrate(uint32_t baudrate) {
+  speed_t s;
+  switch (baudrate) {
+    case 0:
+      s = B0;
+      break;
+
+    case 50:
+      s = B50;
+      break;
+
+    case 75:
+      s = B75;
+      break;
+
+    case 110:
+      s = B110;
+      break;
+
+    case 134:
+      s = B134;
+      break;
+
+    case 150:
+      s = B150;
+      break;
+
+    case 200:
+      s = B200;
+      break;
+
+    case 300:
+      s = B300;
+      break;
+
+    case 600:
+      s = B600;
+      break;
+
+    case 1200:
+      s = B1200;
+      break;
+
+    case 1800:
+      s = B1800;
+      break;
+
+    case 2400:
+      s = B2400;
+      break;
+
+    case 4800:
+      s = B4800;
+      break;
+
+    case 9600:
+      s = B9600;
+      break;
+
+    case 19200:
+      s = B19200;
+      break;
+
+    case 38400:
+      s = B38400;
+      break;
+
+    case 57600:
+      s = B57600;
+      break;
+
+    case 115200:
+      s = B115200;
+      break;
+
+    case 230400:
+      s = B230400;
+      break;
+    default:
+      return EINVAL;
+  }
+
+  struct termios config;
+
+  if (char_interface_->Ioctl(fd_, TCGETS, &config) != 0 ||
+      cfsetspeed(&config, s) != 0 ||
+      char_interface_->Ioctl(fd_, TCSETS, &config) != 0) {
+    LOG(ERROR) << "Failed to set the UART baurate to " << baudrate;
+    return EIO;
+  }
+
+  return 0;
+}
+
+int UartDriverSysfs::Write(const std::vector<uint8_t>& data,
+                           uint32_t* bytes_written) {
+  errno = 0;
+  int ret = char_interface_->Write(fd_, data.data(), data.size());
+
+  if (ret == -1) {
+    PLOG(ERROR) << "Failed to write to UART device";
+    *bytes_written = 0;
+    return EIO;
+  }
+
+  *bytes_written = ret;
+  return 0;
+}
+
+int UartDriverSysfs::Read(std::vector<uint8_t>* data,
+                          uint32_t size,
+                          uint32_t* bytes_read) {
+  errno = 0;
+  data->resize(size);
+
+  int ret = char_interface_->Read(fd_, data->data(), size);
+
+  if (ret == -1) {
+    *bytes_read = 0;
+    data->resize(0);
+    if (errno == EAGAIN) {
+      return EAGAIN;
+    }
+    PLOG(ERROR) << "Failed to read from UART device";
+    return EIO;
+  }
+
+  *bytes_read = ret;
+  data->resize(ret);
+  return 0;
+}
+
+}  // namespace android
diff --git a/peripheralmanager/daemon/uart_driver_sysfs.h b/peripheralmanager/daemon/uart_driver_sysfs.h
new file mode 100644
index 0000000..35085b7
--- /dev/null
+++ b/peripheralmanager/daemon/uart_driver_sysfs.h
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef SYSTEM_PERIPHERALMANAGER_DAEMON_UART_DRIVER_SYSFS_H_
+#define SYSTEM_PERIPHERALMANAGER_DAEMON_UART_DRIVER_SYSFS_H_
+
+#include <stdint.h>
+
+#include <base/macros.h>
+
+#include "char_device.h"
+#include "uart_driver.h"
+
+namespace android {
+
+class UartDriverSysfs : public UartDriverInterface {
+ public:
+  explicit UartDriverSysfs(CharDeviceFactory* factory);
+  ~UartDriverSysfs();
+
+  static std::string Compat() { return "UARTSYSFS"; }
+
+  bool Init(const std::string& name) override;
+
+  int SetBaudrate(uint32_t baudrate) override;
+
+  int Write(const std::vector<uint8_t>& data, uint32_t* bytes_written) override;
+
+  int Read(std::vector<uint8_t>* data,
+           uint32_t size,
+           uint32_t* bytes_read) override;
+
+ private:
+  int fd_;
+  std::string path_;
+
+  CharDeviceFactory* char_device_factory_;
+  std::unique_ptr<CharDeviceInterface> char_interface_;
+
+  DISALLOW_COPY_AND_ASSIGN(UartDriverSysfs);
+};
+
+}  // namespace android
+
+#endif  // SYSTEM_PERIPHERALMANAGER_DAEMON_UART_DRIVER_SYSFS_H_
diff --git a/peripheralmanager/daemon/uart_manager.cc b/peripheralmanager/daemon/uart_manager.cc
new file mode 100644
index 0000000..bc98111
--- /dev/null
+++ b/peripheralmanager/daemon/uart_manager.cc
@@ -0,0 +1,119 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "uart_manager.h"
+
+#include "uart_driver_sysfs.h"
+
+#include <base/logging.h>
+
+namespace android {
+
+std::unique_ptr<UartManager> g_uart_manager;
+
+UartManager* UartManager::GetManager() {
+  if (!g_uart_manager) {
+    g_uart_manager.reset(new UartManager);
+  }
+  return g_uart_manager.get();
+}
+
+void UartManager::ResetManager() {
+  g_uart_manager.reset();
+}
+
+UartManager::UartManager() {}
+
+UartManager::~UartManager() {}
+
+bool UartManager::RegisterDriver(
+    std::unique_ptr<UartDriverInfoBase> driver_info) {
+  std::string key = driver_info->Compat();
+  driver_infos_[key] = std::move(driver_info);
+  return true;
+}
+
+bool UartManager::RegisterUartDevice(const std::string& name,
+                                     const std::string& uart_device_name) {
+  if (uart_devices_.count(name)) {
+    LOG(ERROR) << "Uart device " << name << " is already registered";
+    return false;
+  }
+  uart_devices_[name].name = name;
+  uart_devices_[name].path = uart_device_name;
+  return true;
+}
+
+bool UartManager::SetPinMux(const std::string& name,
+                            const std::string& pin_mux) {
+  auto bus_it = uart_devices_.find(name);
+  if (bus_it == uart_devices_.end()) {
+    LOG(ERROR) << "Uart device " << name << " is not registered";
+    return false;
+  }
+
+  bus_it->second.mux = pin_mux;
+  return true;
+}
+
+std::vector<std::string> UartManager::GetDevicesList() {
+  std::vector<std::string> list;
+  for (const auto& it : uart_devices_) {
+    list.push_back(it.first);
+  }
+  return list;
+}
+
+bool UartManager::HasUartDevice(const std::string& name) {
+  return uart_devices_.count(name);
+}
+
+std::unique_ptr<UartDevice> UartManager::OpenUartDevice(
+    const std::string& name) {
+  // Get the Bus from the BSP.
+  auto bus_it = uart_devices_.find(name);
+  if (bus_it == uart_devices_.end())
+    return nullptr;
+
+  // Check its not already in use
+  if (bus_it->second.driver_)
+    return nullptr;
+
+  // Find a driver.
+  // Currently there is only hardcoded support for UARTSYSFS
+  auto driver_info_it = driver_infos_.find(UartDriverSysfs::Compat());
+
+  // Fail if there is no driver.
+  if (driver_info_it == driver_infos_.end())
+    return nullptr;
+
+  std::unique_ptr<UartDriverInterface> driver(driver_info_it->second->Probe());
+
+  if (!driver->Init(bus_it->second.path))
+    return nullptr;
+
+  // Set Pin muxing.
+  if (!bus_it->second.mux.empty()) {
+    PinMuxManager::GetPinMuxManager()->SetSource(bus_it->second.mux,
+                                                 bus_it->second.mux);
+  }
+
+  bus_it->second.driver_ = std::move(driver);
+
+  return std::unique_ptr<UartDevice>(new UartDevice(&(bus_it->second)));
+}
+
+}  // namespace android
diff --git a/peripheralmanager/daemon/uart_manager.h b/peripheralmanager/daemon/uart_manager.h
new file mode 100644
index 0000000..ba8fa51
--- /dev/null
+++ b/peripheralmanager/daemon/uart_manager.h
@@ -0,0 +1,92 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef SYSTEM_PERIPHERALMANAGER_DAEMON_UART_MANAGER_H_
+#define SYSTEM_PERIPHERALMANAGER_DAEMON_UART_MANAGER_H_
+
+#include <stdint.h>
+
+#include <map>
+#include <memory>
+#include <string>
+#include <vector>
+
+#include <base/macros.h>
+
+#include "pin_mux_manager.h"
+#include "uart_driver.h"
+
+namespace android {
+
+struct UartSysfs {
+  std::string name;
+  std::string path;
+  std::string mux;
+  std::unique_ptr<UartDriverInterface> driver_;
+};
+
+class UartDevice {
+ public:
+  explicit UartDevice(UartSysfs* uart_device) : uart_device_(uart_device) {}
+  ~UartDevice() { uart_device_->driver_.reset(); }
+
+  int SetBaudrate(uint32_t baudrate) {
+    return uart_device_->driver_->SetBaudrate(baudrate);
+  }
+
+  int Write(const std::vector<uint8_t>& data, uint32_t* bytes_written) {
+    return uart_device_->driver_->Write(data, bytes_written);
+  }
+
+  int Read(std::vector<uint8_t>* data, uint32_t size, uint32_t* bytes_read) {
+    return uart_device_->driver_->Read(data, size, bytes_read);
+  }
+
+ private:
+  UartSysfs* uart_device_;
+};
+
+class UartManager {
+ public:
+  ~UartManager();
+
+  // Get the singleton.
+  static UartManager* GetManager();
+  static void ResetManager();
+
+  // Used by the BSP to tell PMan of an sysfs uart_device.
+  bool RegisterUartDevice(const std::string& name, const std::string& path);
+  bool SetPinMux(const std::string& name, const std::string& mux);
+
+  std::vector<std::string> GetDevicesList();
+  bool HasUartDevice(const std::string& name);
+
+  bool RegisterDriver(std::unique_ptr<UartDriverInfoBase> driver_info);
+
+  std::unique_ptr<UartDevice> OpenUartDevice(const std::string& name);
+
+ private:
+  UartManager();
+
+  std::map<std::string, std::unique_ptr<UartDriverInfoBase>> driver_infos_;
+  std::map<std::string, UartSysfs> uart_devices_;
+
+  DISALLOW_COPY_AND_ASSIGN(UartManager);
+};
+
+}  // namespace android
+
+#endif  // SYSTEM_PERIPHERALMANAGER_DAEMON_UART_MANAGER_H_
diff --git a/peripheralmanager/example/Android.mk b/peripheralmanager/example/Android.mk
new file mode 100644
index 0000000..a4099fb
--- /dev/null
+++ b/peripheralmanager/example/Android.mk
@@ -0,0 +1,147 @@
+#
+# Copyright (C) 2015 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+LOCAL_PATH := $(call my-dir)
+
+# Flips a GPIO on and off.
+# ========================================================
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := peripheralman_gpio_flip
+LOCAL_CPP_EXTENSION := .cc
+LOCAL_CFLAGS := -Wall -Werror -Wno-unused-parameter
+LOCAL_CFLAGS += -Wno-sign-promo  # for libchrome
+LOCAL_SHARED_LIBRARIES := \
+  libbrillo \
+  libchrome \
+  libperipheralman \
+  libutils \
+
+LOCAL_SRC_FILES := \
+  gpio_flip_example.cc \
+
+include $(BUILD_EXECUTABLE)
+
+# Watches the state of a gpio with interrupts.
+# ========================================================
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := peripheralman_gpio_interrupt
+LOCAL_CPP_EXTENSION := .cc
+LOCAL_CFLAGS := -Wall -Werror -Wno-unused-parameter
+LOCAL_CFLAGS += -Wno-sign-promo  # for libchrome
+LOCAL_SHARED_LIBRARIES := \
+  libbrillo \
+  libchrome \
+  libperipheralman \
+  libutils \
+
+LOCAL_SRC_FILES := \
+  gpio_interrupt_example.cc \
+
+include $(BUILD_EXECUTABLE)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := pio_flash_apa10c
+LOCAL_CPP_EXTENSION := .cc
+LOCAL_CFLAGS := -Wall -Werror -Wno-unused-parameter
+LOCAL_CFLAGS += -Wno-sign-promo  # for libchrome
+LOCAL_SHARED_LIBRARIES := \
+  libbrillo \
+  libchrome \
+  libperipheralman \
+  libutils \
+
+LOCAL_SRC_FILES := \
+  pio_flash_apa10c.cc \
+
+include $(BUILD_EXECUTABLE)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := peripheralman_blink_led
+LOCAL_CPP_EXTENSION := .cc
+LOCAL_CFLAGS := -Wall -Werror -Wno-unused-parameter
+LOCAL_CFLAGS += -Wno-sign-promo  # for libchrome
+LOCAL_SHARED_LIBRARIES := \
+  libbrillo \
+  libchrome \
+  libperipheralman \
+  libutils \
+
+LOCAL_SRC_FILES := \
+  led_example.cc \
+
+include $(BUILD_EXECUTABLE)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := pio_mcp9808
+LOCAL_CPP_EXTENSION := .cc
+LOCAL_CFLAGS := -Wall -Werror -Wno-unused-parameter
+LOCAL_CFLAGS += -Wno-sign-promo  # for libchrome
+LOCAL_SHARED_LIBRARIES := \
+  libbrillo \
+  libchrome \
+  libperipheralman \
+  libutils \
+
+LOCAL_SRC_FILES := \
+  pio_mcp9808.cc \
+
+include $(BUILD_EXECUTABLE)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := pio_gy521
+LOCAL_CPP_EXTENSION := .cc
+LOCAL_CFLAGS := -Wall -Werror -Wno-unused-parameter
+LOCAL_CFLAGS += -Wno-sign-promo  # for libchrome
+LOCAL_SHARED_LIBRARIES := \
+  libbrillo \
+  libchrome \
+  libperipheralman \
+  libutils \
+
+LOCAL_SRC_FILES := \
+  pio_gy521.cc \
+
+include $(BUILD_EXECUTABLE)
+
+# Check that headers are C89 compatible.
+include $(CLEAR_VARS)
+LOCAL_MODULE := compatibility_test
+LOCAL_CFLAGS := -Wall -Wextra -std=c89 -pedantic -Wmissing-prototypes \
+  -Wstrict-prototypes -Wold-style-definition -Wno-comment
+
+LOCAL_SHARED_LIBRARIES := libperipheralman
+LOCAL_STATIC_LIBRARIES := peripheral_manager_hal_headers
+
+LOCAL_SRC_FILES := headers_are_c89.c
+include $(BUILD_STATIC_LIBRARY)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := pio_uart
+LOCAL_CPP_EXTENSION := .cc
+LOCAL_CFLAGS := -Wall -Werror -Wno-unused-parameter
+LOCAL_CFLAGS += -Wno-sign-promo  # for libchrome
+LOCAL_SHARED_LIBRARIES := \
+  libbrillo \
+  libchrome \
+  libperipheralman \
+  libutils \
+
+LOCAL_SRC_FILES := \
+  pio_uart.cc \
+
+include $(BUILD_EXECUTABLE)
diff --git a/peripheralmanager/example/gpio_flip_example.cc b/peripheralmanager/example/gpio_flip_example.cc
new file mode 100644
index 0000000..6c6b267
--- /dev/null
+++ b/peripheralmanager/example/gpio_flip_example.cc
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <unistd.h>
+
+#include <memory>
+
+#include <base/logging.h>
+#include <brillo/flag_helper.h>
+
+#include <peripheralmanager/peripheral_manager_client.h>
+
+int main(int argc, char* argv[]) {
+  DEFINE_string(pin, "", "Pin to toggle");
+  brillo::FlagHelper::Init(argc, argv, "Example PeripheralManager client.");
+  logging::InitLogging(logging::LoggingSettings());
+
+  std::string pin_name = "IO13";
+  if (!FLAGS_pin.empty())
+    pin_name = FLAGS_pin;
+
+  LOG(INFO) << "Toggling Pin " << pin_name;
+
+  // Get a client to the PeripheralManager.
+  BPeripheralManagerClient* client = BPeripheralManagerClient_new();
+
+  if (!client) {
+    LOG(ERROR) << "Failed to connect to client";
+    return 1;
+  }
+
+  // Open GPIO pin.
+  BGpio* my_gpio;
+  int ret =
+      BPeripheralManagerClient_openGpio(client, pin_name.c_str(), &my_gpio);
+  if (ret) {
+    LOG(ERROR) << "Failed to open Gpio: " << strerror(ret);
+    return 1;
+  }
+
+  // Set the direction to out.
+  ret = BGpio_setDirection(my_gpio, DIRECTION_OUT_INITIALLY_HIGH);
+  if (ret) {
+    LOG(ERROR) << "Failed to set gpio pin direction: " << strerror(ret);
+    return 1;
+  }
+
+  // Toggle the output.
+  BGpio_setValue(my_gpio, 0);
+  sleep(1);
+  BGpio_setValue(my_gpio, 1);
+
+  // Release the gpio pin
+  BGpio_delete(my_gpio);
+
+  // Close the connection to PeripheralManager.
+  BPeripheralManagerClient_delete(client);
+
+  LOG(INFO) << "Exiting";
+  return 0;
+}
diff --git a/peripheralmanager/example/gpio_interrupt_example.cc b/peripheralmanager/example/gpio_interrupt_example.cc
new file mode 100644
index 0000000..3261f81
--- /dev/null
+++ b/peripheralmanager/example/gpio_interrupt_example.cc
@@ -0,0 +1,108 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <poll.h>
+#include <sys/select.h>
+#include <unistd.h>
+
+#include <memory>
+
+#include <base/logging.h>
+#include <brillo/flag_helper.h>
+
+#include <peripheralmanager/peripheral_manager_client.h>
+
+int main(int argc, char* argv[]) {
+  DEFINE_string(pin, "", "Pin to watch");
+  DEFINE_bool(select, false, "Use select instead of poll");
+  brillo::FlagHelper::Init(argc, argv, "Watches a GPIO.");
+  logging::InitLogging(logging::LoggingSettings());
+
+  std::string pin_name = "IO1";
+  if (!FLAGS_pin.empty())
+    pin_name = FLAGS_pin;
+
+  // Get a client to the PeripheralManager.
+  BPeripheralManagerClient* client = BPeripheralManagerClient_new();
+
+  if (!client) {
+    LOG(ERROR) << "Failed to connect to client";
+    return 1;
+  }
+
+  // Open GPIO pin.
+  BGpio* my_gpio;
+  if (BPeripheralManagerClient_openGpio(client, pin_name.c_str(), &my_gpio)) {
+    LOG(ERROR) << "Failed to open Gpio";
+    return 1;
+  }
+
+  // Set the direction to in.
+  if (BGpio_setDirection(my_gpio, DIRECTION_IN)) {
+    LOG(ERROR) << "Failed to set gpio pin direction";
+    return 1;
+  }
+
+  // Set the edge trigger type for interrupts.
+  if (BGpio_setEdgeTriggerType(my_gpio, BOTH_EDGE)) {
+    LOG(ERROR) << "failed to set the edge type";
+    return 1;
+  }
+
+  // Get the file descriptor used to poll for data.
+  int fd = -1;
+  if (BGpio_getPollingFd(my_gpio, &fd)) {
+    LOG(ERROR) << "failed to get the fd";
+    return 1;
+  }
+
+  if (FLAGS_select) {
+    fd_set ifds;
+    FD_ZERO(&ifds);
+    FD_SET(fd, &ifds);
+
+    for (int i = 0; i < 30; i++) {
+      select(fd + 1, NULL, NULL, &ifds, NULL);
+      LOG(INFO) << "received event";
+      BGpio_ackInterruptEvent(fd);
+    }
+  } else {
+    struct pollfd poller = {
+      .fd = fd,
+      .events = POLLPRI | POLLERR,
+      .revents = 0,
+    };
+
+    for (int i = 0; i < 30; i++) {
+      // Poll with no timeout.
+      poll(&poller, 1, -1);
+      LOG(INFO) << "received an event ";
+      BGpio_ackInterruptEvent(fd);
+      poller.revents = 0;
+    }
+  }
+
+  close(fd);
+
+  // Release the gpio pin
+  BGpio_delete(my_gpio);
+
+  // Close the connection to PeripheralManager.
+  BPeripheralManagerClient_delete(client);
+
+  LOG(INFO) << "Exiting";
+  return 0;
+}
diff --git a/peripheralmanager/example/headers_are_c89.c b/peripheralmanager/example/headers_are_c89.c
new file mode 100644
index 0000000..ff13b4d
--- /dev/null
+++ b/peripheralmanager/example/headers_are_c89.c
@@ -0,0 +1,18 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "hardware/peripheral_io.h"
+#include "peripheralmanager/peripheral_manager_client.h"
diff --git a/peripheralmanager/example/led_example.cc b/peripheralmanager/example/led_example.cc
new file mode 100644
index 0000000..ab5c7b3
--- /dev/null
+++ b/peripheralmanager/example/led_example.cc
@@ -0,0 +1,95 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <unistd.h>
+
+#include <memory>
+
+#include <base/logging.h>
+#include <brillo/flag_helper.h>
+
+#include <peripheralmanager/peripheral_manager_client.h>
+
+int main(int argc, char* argv[]) {
+  DEFINE_string(led, "", "Led to toggle");
+  brillo::FlagHelper::Init(argc, argv, "Example client blinking a light.");
+  logging::InitLogging(logging::LoggingSettings());
+
+  if (FLAGS_led.empty()) {
+    LOG(ERROR) << "Led name not specified.";
+    return 1;
+  }
+
+  LOG(INFO) << "Blinking " << FLAGS_led;
+
+  // Get a client to the PeripheralManager.
+  BPeripheralManagerClient* client = BPeripheralManagerClient_new();
+
+  if (!client) {
+    LOG(ERROR) << "Failed to connect to client";
+    return 1;
+  }
+
+  // Open the LED.
+  BLed* led;
+  int ret = BPeripheralManagerClient_openLed(client, FLAGS_led.c_str(), &led);
+  if (ret) {
+    LOG(ERROR) << "Failed to open LED: " << strerror(ret);
+    return 1;
+  }
+
+  uint32_t max_brightness = 0;
+
+  // Get the maximum brightness possible.
+  ret = BLed_getMaxBrightness(led, &max_brightness);
+  if (ret) {
+    LOG(ERROR) << "Failed to get the maximum brightness: " << strerror(ret);
+    return 1;
+  }
+
+  // Toggle the output.
+  BLed_setBrightness(led, 0);
+  sleep(1);
+  BLed_setBrightness(led, max_brightness / 2);
+  sleep(1);
+  BLed_setBrightness(led, max_brightness);
+  sleep(1);
+  BLed_setBrightness(led, max_brightness / 2);
+  sleep(1);
+  BLed_setBrightness(led, 0);
+
+  // Make sure the led is turned off.
+  uint32_t brightness;
+  ret = BLed_getBrightness(led, &brightness);
+  if (ret) {
+    LOG(ERROR) << "Failed to read the brightness: " << strerror(ret);
+    return 1;
+  }
+
+  if (brightness != 0) {
+    LOG(ERROR) << "Failed to turn the LED off, led is at: "
+               << std::to_string(brightness);
+  }
+
+  // Release the LED
+  BLed_delete(led);
+
+  // Close the connection to PeripheralManager.
+  BPeripheralManagerClient_delete(client);
+
+  LOG(INFO) << "Exiting";
+  return 0;
+}
diff --git a/peripheralmanager/example/pio_flash_apa10c.cc b/peripheralmanager/example/pio_flash_apa10c.cc
new file mode 100644
index 0000000..82dfa33
--- /dev/null
+++ b/peripheralmanager/example/pio_flash_apa10c.cc
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <unistd.h>
+
+#include <memory>
+
+#include <base/logging.h>
+#include <brillo/flag_helper.h>
+
+#include <peripheralmanager/peripheral_manager_client.h>
+
+void SetLed(const BSpiDevice* my_spi, uint8_t r, uint8_t g, uint8_t b) {
+  uint8_t start_frame[] = {0x00, 0x00, 0x00, 0x00};
+  uint8_t on_frame[4] = {0xff, 0x00, 0x00, 0x00};
+  uint8_t end_frame[] = {0xff, 0xff, 0xff, 0xff};
+  on_frame[1] = b;
+  on_frame[2] = g;
+  on_frame[3] = r;
+  BSpiDevice_writeBuffer(my_spi, start_frame, sizeof(start_frame));
+  BSpiDevice_writeBuffer(my_spi, on_frame, sizeof(on_frame));
+  BSpiDevice_writeBuffer(my_spi, end_frame, sizeof(end_frame));
+}
+
+int main(int argc, char* argv[]) {
+  brillo::FlagHelper::Init(argc, argv, "PeripheralManager client.");
+  logging::InitLogging(logging::LoggingSettings());
+
+  LOG(INFO) << "PeripheralManager Client";
+
+  // Get a client to the PeripheralManager.
+  BPeripheralManagerClient* client = BPeripheralManagerClient_new();
+
+  if (!client) {
+    LOG(ERROR) << "Failed to connect to client";
+    return 1;
+  }
+
+  // Open SPI bus.
+  BSpiDevice* my_spi;
+  int ret = BPeripheralManagerClient_openSpiDevice(client, "SPI2", &my_spi);
+  if (ret) {
+    LOG(ERROR) << "Failed to open Spi: " << strerror(ret);
+    return 1;
+  }
+
+  BSpiDevice_setFrequency(my_spi, 400000);
+
+  SetLed(my_spi, 0xff, 0x0, 0x0);
+  sleep(1);
+  SetLed(my_spi, 0x00, 0xff, 0x0);
+  sleep(1);
+  SetLed(my_spi, 0x00, 0x0, 0xff);
+  sleep(1);
+
+  BSpiDevice_delete(my_spi);
+
+  // Close the connection to PeripheralManager.
+  BPeripheralManagerClient_delete(client);
+
+  LOG(INFO) << "Exiting";
+  return 0;
+}
diff --git a/peripheralmanager/example/pio_gy521.cc b/peripheralmanager/example/pio_gy521.cc
new file mode 100644
index 0000000..ec9296f
--- /dev/null
+++ b/peripheralmanager/example/pio_gy521.cc
@@ -0,0 +1,105 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <arpa/inet.h>
+#include <unistd.h>
+
+#include <memory>
+
+#include <base/logging.h>
+#include <brillo/flag_helper.h>
+
+#include <peripheralmanager/peripheral_manager_client.h>
+
+int16_t swap_bytes(int16_t i) {
+  return ((i & 0x00FF) << 8) + ((i & 0xFF00) >> 8);
+}
+
+int main(int argc, char* argv[]) {
+  brillo::FlagHelper::Init(argc, argv, "PeripheralManager example.");
+  logging::InitLogging(logging::LoggingSettings());
+
+  // Get a client to the PeripheralManager.
+  BPeripheralManagerClient* client = BPeripheralManagerClient_new();
+
+  if (!client) {
+    LOG(ERROR) << "Failed to connect to client";
+    return 1;
+  }
+
+  // Open I2C device.
+  BI2cDevice* i2c_device;
+  int ret =
+      BPeripheralManagerClient_openI2cDevice(client, "I2C6", 0x68, &i2c_device);
+  if (ret) {
+    LOG(ERROR) << "Failed to open I2C: " << strerror(ret);
+    return 1;
+  }
+
+  // Turn the sensor on.
+  ret = BI2cDevice_writeRegByte(i2c_device, 0x6B, 0);
+  if (ret) {
+    LOG(ERROR) << "Failed to setup the device: " << strerror(ret);
+    return 1;
+  }
+
+  // Read the "who am I" register (contains the device address).
+  uint8_t address;
+  ret = BI2cDevice_readRegByte(i2c_device, 0x75, &address);
+  if (ret) {
+    LOG(ERROR) << "Failed to read the WHO AM I register: " << strerror(ret);
+    return 1;
+  }
+  printf("I am at address is: 0x%X\n", address);
+
+  int16_t temp = 0;
+  ret = BI2cDevice_readRegWord(
+      i2c_device, 0x41, reinterpret_cast<uint16_t*>(&temp));
+  if (ret) {
+    LOG(ERROR) << "Failed to read the temp: " << strerror(ret);
+    return 1;
+  }
+  temp = ntohs(temp);
+  float t = temp;
+  printf("temp is: %.02f degrees Celsius.\n", t / 340 + 36.53);
+
+  for (int j = 0; j < 50; j++) {
+
+    // Read the values of the accelerometer.
+    int16_t accel_data[3];
+
+    uint32_t read;
+    ret = BI2cDevice_readRegBuffer(i2c_device, 0x3B, &accel_data, 6, &read);
+    if (ret || read != 6) {
+      LOG(ERROR) << "Failed to read the buffer: " << strerror(ret);
+      return 1;
+    }
+
+    printf("Accelerometer values: X=%i, Y=%i, Z=%i\n",
+           swap_bytes(accel_data[0]),
+           swap_bytes(accel_data[1]),
+           swap_bytes(accel_data[2]));
+
+    sleep(1);
+  }
+
+  BI2cDevice_delete(i2c_device);
+
+  // Close the connection to PeripheralManager.
+  BPeripheralManagerClient_delete(client);
+
+  return 0;
+}
diff --git a/peripheralmanager/example/pio_mcp9808.cc b/peripheralmanager/example/pio_mcp9808.cc
new file mode 100644
index 0000000..446afbf
--- /dev/null
+++ b/peripheralmanager/example/pio_mcp9808.cc
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <arpa/inet.h>
+#include <unistd.h>
+
+#include <memory>
+
+#include <base/logging.h>
+#include <brillo/flag_helper.h>
+
+#include <peripheralmanager/peripheral_manager_client.h>
+
+int main(int argc, char* argv[]) {
+  brillo::FlagHelper::Init(argc, argv, "PeripheralManager client.");
+  logging::InitLogging(logging::LoggingSettings());
+
+  // Get a client to the PeripheralManager.
+  BPeripheralManagerClient* client = BPeripheralManagerClient_new();
+
+  if (!client) {
+    LOG(ERROR) << "Failed to connect to client";
+    return 1;
+  }
+
+  // Open I2C bus.
+  BI2cDevice* i2c_device;
+  int ret =
+      BPeripheralManagerClient_openI2cDevice(client, "I2C6", 0x18, &i2c_device);
+  if (ret) {
+    LOG(ERROR) << "Failed to open I2C: " << strerror(ret);
+    return 1;
+  }
+
+  uint16_t val = 0;
+  BI2cDevice_readRegWord(i2c_device, 0x05, &val);
+
+  val = ntohs(val);
+  float temp = (val >> 4) & 0xFF;
+  temp += (float)(val & 0xF) / 16;
+  printf("Temp: %f\n", temp);
+
+  BI2cDevice_delete(i2c_device);
+
+  // Close the connection to PeripheralManager.
+  BPeripheralManagerClient_delete(client);
+
+  return 0;
+}
diff --git a/peripheralmanager/example/pio_uart.cc b/peripheralmanager/example/pio_uart.cc
new file mode 100644
index 0000000..628a746
--- /dev/null
+++ b/peripheralmanager/example/pio_uart.cc
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <base/logging.h>
+#include <brillo/flag_helper.h>
+
+#include <peripheralmanager/peripheral_manager_client.h>
+
+int main(int argc, char* argv[]) {
+  brillo::FlagHelper::Init(argc, argv, "PeripheralManager client.");
+  logging::InitLogging(logging::LoggingSettings());
+
+  // Get a client to the PeripheralManager.
+  BPeripheralManagerClient* client = BPeripheralManagerClient_new();
+
+  if (!client) {
+    LOG(ERROR) << "Failed to connect to client";
+    return 1;
+  }
+
+  BUartDevice* uart;
+  int ret = BPeripheralManagerClient_openUartDevice(client, "UART1", &uart);
+  if (ret) {
+    LOG(ERROR) << "Failed to open UART device";
+    return 1;
+  }
+
+  ret = BUartDevice_setBaudrate(uart, 9600);
+
+  char greeting[] = "What is your name ?\n";
+  uint32_t written = 0;
+  ret = BUartDevice_write(uart, greeting, strlen(greeting), &written);
+  if (ret) {
+    LOG(ERROR) << "failed to write: " << strerror(ret);
+    return 1;
+  }
+
+  std::string name = "";
+
+  while (name.size() < 40) {
+    // If the user entered a newline, everything before is the name.
+    auto first_newline = name.find(13);
+    if (first_newline != std::string::npos) {
+      name.resize(first_newline);
+      break;
+    }
+
+    char buffer[40];
+    uint32_t bytes_read = 0;
+
+    // Read some data.
+    ret = BUartDevice_read(uart, buffer, 40, &bytes_read);
+    if (ret != 0 && ret != EAGAIN) {
+      LOG(ERROR) << "failed to read: " << strerror(ret);
+      return 1;
+    }
+    LOG(INFO) << "read " << bytes_read << "bytes";
+    name.append(buffer, bytes_read);
+
+    // Wait a little before reading again.
+    // This should be replaced by a more efficient polling mechanism when it is
+    // ready.
+    sleep(2);
+  }
+
+  LOG(INFO) << "hello " << name;
+
+  // Release the UART object.
+  BUartDevice_delete(uart);
+
+  // Close the connection to PeripheralManager.
+  BPeripheralManagerClient_delete(client);
+
+  LOG(INFO) << "Exiting";
+  return 0;
+}
diff --git a/peripheralmanager/hal/Android.mk b/peripheralmanager/hal/Android.mk
new file mode 100644
index 0000000..9e0d4e1
--- /dev/null
+++ b/peripheralmanager/hal/Android.mk
@@ -0,0 +1,22 @@
+#
+# Copyright (C) 2016 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := peripheral_manager_hal_headers
+LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)
+include $(BUILD_STATIC_LIBRARY)
diff --git a/peripheralmanager/hal/hardware/peripheral_io.h b/peripheralmanager/hal/hardware/peripheral_io.h
new file mode 100644
index 0000000..624e83b
--- /dev/null
+++ b/peripheralmanager/hal/hardware/peripheral_io.h
@@ -0,0 +1,286 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_PERIPHERAL_IO_INTERFACE_H
+#define ANDROID_PERIPHERAL_IO_INTERFACE_H
+
+#include <stdint.h>
+#include <sys/cdefs.h>
+#include <sys/types.h>
+
+#include <hardware/hardware.h>
+
+__BEGIN_DECLS
+
+/**
+ * Id of this module.
+ */
+#define PERIPHERAL_IO_HARDWARE_MODULE_ID "peripheral_io"
+
+/**
+ * Possible GPIO direction configuration.
+ */
+typedef enum {
+  GPIO_DIRECTION_IN,      /** Input */
+  GPIO_DIRECTION_OUT_LOW, /** Output, initially low */
+  GPIO_DIRECTION_OUT_HIGH /** Output, initially high */
+} gpio_direction_t;
+
+/**
+ * Callback to enable a given pinmux source on a specific pin.
+ *
+ * Args:
+ *  pin: Name of the pin.
+ *  source: Name of the pinmux source to enable. When NULL, setup the pinmux
+ *          to enable GPIO on this pin.
+ *
+ * Returns:
+ *  0 on success, errno on error.
+ */
+typedef int (*pin_mux_cb)(const char* pin, const char* source);
+
+/**
+ * Callback to set the direction of a given GPIO.
+ *
+ * Args:
+ *  pin: Name of the pin to configure.
+ *  dir: Direction to set. One of gpio_direction_t.
+ *
+ * Returns:
+ *  0 on success, errno on error.
+ */
+typedef int (*pin_mux_direction_cb)(const char* pin, int dir);
+
+/**
+ * Callbacks used by peripheral manager to configure given pins.
+ */
+typedef struct pin_mux_callbacks {
+  pin_mux_cb mux_cb;
+  pin_mux_direction_cb direction_cb;
+} pin_mux_callbacks;
+
+/**
+ * Callbacks into peripheral manager.
+ *
+ * Those callbacks must be used in register_devices to declare the available
+ * interfaces to peripheral manager.
+ *
+ * All peripherals are referred to by their friendly name.
+ * The friendly name is a string, used to refer to a given peripheral (ex: gpio
+ * name, spi bus name) that is simple to understand, well documented for the
+ * board and unambiguous.
+ *
+ * Before coming up with a new naming scheme, consider:
+ * - Using an existing naming scheme: if the board provides an arduino pinout, a
+ *   raspberry Pi pinout or a 96 boards pinout, use it.
+ * - Using the names written on the board next to the physical ports if any.
+ * - Using the documented name when widely available.
+ *   Referring to the same pin or peripheral by two different names in the
+ *   documentation and in peripheral manager would be confusing to the user.
+ *
+ * If coming up with a new name, use only simple characters (ideally, A-Z, 0-9,
+ * -, _).
+ */
+typedef struct peripheral_registration_cb_t {
+  /**
+   * Register a pin.
+   *
+   * Args:
+   *  name: Friendly name (see definition above) of the pin.
+   *  callbacks: Callbacks used to set up pinmuxes.
+   *
+   * Returns:
+   *  0 on success, errno on error.
+   */
+  int (*register_pin)(const char* name, int gpio, pin_mux_callbacks callbacks);
+
+  /**
+   * Register a pin group.
+   *
+   * Args:
+   *  name: Name of the group.
+   *  pins: List of pin names that are part of the group.
+   *  nr_pins: Size of |pins|.
+   *
+   * Returns:
+   *  0 on success, errno on error.
+   */
+  int (*register_pin_group)(const char* name, char** pins, size_t nr_pins);
+
+  /**
+   * Register a pinmux source.
+   *
+   * Args:
+   *  name: Name of the pinmux source.
+   *  groups: List of possible pinmux groups this source can come up on.
+   *  nr_groups: Size of |groups|.
+   *
+   * Returns:
+   *  0 on success, errno on error.
+   */
+  int (*register_source)(const char* name, char** groups, size_t nr_groups);
+
+  /**
+   * Register a simple source, mapped to a single pin group.
+   *
+   * This convenience function replaces the two calls to register_pin_group and
+   * register_source in most cases.
+   *
+   * Args:
+   *  name: Name of the pinmux source.
+   *  pins: List of pins this source comes up on.
+   *  nr_pins: Size of |pins|.
+   *
+   * Returns:
+   *  0 on success, errno on error.
+   */
+  int (*register_simple_source)(const char* name,
+                                const char** pins,
+                                size_t nr_pins);
+
+  /**
+   * Register a sysfs backed GPIO.
+   *
+   * Args:
+   *  name: Friendly name of the GPIO.
+   *  index: Index of the gpio in sysfs.
+   *
+   * Returns:
+   *  0 on success, errno on error.
+   */
+  int (*register_gpio_sysfs)(const char* name, uint32_t index);
+
+  /**
+   * Set the pinmux for a given GPIO.
+   *
+   * Args:
+   *  name: Friendly name of the pin.
+   *  source: Name of the pinmux source.
+   *
+   * Returns:
+   *  0 on success, errno on error.
+   */
+  int (*set_gpio_pin_mux)(const char* name, const char* source);
+
+  /**
+   * Register a SPI device.
+   *
+   * Args:
+   *  name: Friendly name of the device.
+   *  bus: Bus number.
+   *  cs: Chip select.
+   *
+   * Returns:
+   *  0 on success, errno on error.
+   */
+  int (*register_spi_dev_bus)(const char* name, uint32_t bus, uint32_t cs);
+
+  /**
+   * Set the pinmux for a given SPI device.
+   *
+   * Args:
+   *  name: Friendly name of the device.
+   *  source: Name of the pinmuxing source.
+   *
+   * Returns:
+   *  0 on success, errno on error.
+   */
+  int (*set_spi_pin_mux)(const char* name, const char* source);
+
+  /**
+   * Register a sysfs-backed LED.
+   *
+   * Args:
+   *  name: Friendly name of the LED.
+   *  sysfs_name: Name of the device in sysfs.
+   *
+   * Returns:
+   *  0 on success, errno on error.
+   */
+  int (*register_led_sysfs)(const char* name, const char* sysfs_name);
+
+  /**
+   * Register a UART bus.
+   *
+   * Args:
+   *  name: Friendly name of the bus.
+   *  dev_name: Name of the device in sysfs.
+   *
+   * Returns:
+   *  0 on success, errno on error.
+   */
+  int (*register_uart_bus)(const char* name, const char* dev_name);
+
+  /**
+   * Set the pinmux for a given UART bus.
+   *
+   * Args:
+   *  name: Friendly name of the UART bus.
+   *  source: Name of the pinmuxing source.
+   *
+   * Returns:
+   *  0 on success, errno on error.
+   */
+  int (*set_uart_pin_mux)(const char* name, const char* source);
+
+  /**
+   * Register an I2C bus.
+   *
+   * Args:
+   *  name: Friendly name of the I2C device.
+   *  bus: I2C bus number.
+   *
+   * Returns:
+   *  0 on success, errno on error.
+   */
+  int (*register_i2c_dev_bus)(const char* name, uint32_t bus);
+
+  /**
+   * Set the pinmux for a given I2C bus.
+   *
+   * Args:
+   *  name: Friendly name of the I2C bus.
+   *  source: Name of the pinmuxing source.
+   *
+   * Returns:
+   *  0 on success, errno on error.
+   */
+  int (*set_i2c_pin_mux)(const char* name, const char* source);
+
+} peripheral_registration_cb_t;
+
+typedef struct peripheral_io_module_t peripheral_io_module_t;
+
+struct peripheral_io_module_t {
+  struct hw_module_t common;
+
+  /**
+   * Register all available devices with the peripheral manager.
+   *
+   * Arguments:
+   *  dev: Pointer to the peripheral_io module.
+   *  callbacks: Callbacks into peripheral manager to register devices.
+   *
+   * Returns:
+   *  0 on success, errno on error.
+   */
+  int (*register_devices)(const peripheral_io_module_t* dev,
+                          const peripheral_registration_cb_t* callbacks);
+};
+
+__END_DECLS
+
+#endif  // ANDROID_PERIPHERAL_IO_INTERFACE_H
diff --git a/peripheralmanager/include/peripheralmanager/gpio.h b/peripheralmanager/include/peripheralmanager/gpio.h
new file mode 100644
index 0000000..d55a0ae
--- /dev/null
+++ b/peripheralmanager/include/peripheralmanager/gpio.h
@@ -0,0 +1,109 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef SYSTEM_PERIPHERALMANAGER_GPIO_H_
+#define SYSTEM_PERIPHERALMANAGER_GPIO_H_
+
+#include <sys/cdefs.h>
+#include <sys/types.h>
+
+__BEGIN_DECLS
+
+/// @defgroup Gpio Gpio Interface
+/// @brief Functions to control gpio pins.
+///
+/// These functions can be used to control gpio.
+/// @{
+
+/// Edge trigger types.
+enum {
+  NONE_EDGE,  /**<  None */
+  RISING_EDGE,  /**<  Rising edge */
+  FALLING_EDGE,  /**<  Falling edge */
+  BOTH_EDGE  /**<  Both edges */
+};
+
+/// GPIO direction types.
+enum {
+  DIRECTION_IN,  /**<  Input mode */
+  DIRECTION_OUT_INITIALLY_HIGH,  /**<  Output mode, initially set to high */
+  DIRECTION_OUT_INITIALLY_LOW  /**<  Output mode, initially set to low */
+};
+
+/// Possible active types.
+enum {
+  ACTIVE_LOW,  /**<  Active Low */
+  ACTIVE_HIGH  /**<  Active High */
+};
+
+typedef struct BGpio BGpio;
+
+
+
+/// Sets the GPIO direction to output.
+/// @param gpio Pointer to the BGpio struct
+/// @param direction One of DIRECTION_IN,
+/// DIRECTION_OUT_INITIALLY_HIGH, DIRECTION_OUT_INITIALLY_LOW.
+/// @return 0 on success, errno on error.
+int BGpio_setDirection(const BGpio* gpio, int direction);
+
+/// Sets the interrupt edge trigger type.
+/// @param gpio Pointer to the BGpio struct
+/// @param type One of NONE_EDGE, RISING_EDGE, FALLING_EDGE or BOTH_EDGE.
+/// @return 0 on success, errno on error.
+int BGpio_setEdgeTriggerType(const BGpio* gpio, int type);
+
+/// Sets the GPIO’s active low/high status.
+/// @param gpio Pointer to the BGpio struct.
+/// @param type One of ACTIVE_HIGH, ACTIVE_LOW.
+/// @return 0 on success, errno on error.
+int BGpio_setActiveType(const BGpio* gpio, int type);
+
+/// Sets the GPIO value (for output GPIO only).
+/// @param gpio Pointer to the BGpio struct.
+/// @param value Value to set.
+/// @return 0 on success, errno on error.
+int BGpio_setValue(const BGpio* gpio, int value);
+
+/// Gets the GPIO value (for input GPIO only).
+/// @param gpio Pointer to the BGpio struct.
+/// @param value Output pointer to the value of the GPIO.
+/// @return 0 on success, errno on error.
+int BGpio_getValue(const BGpio* gpio, int* value);
+
+/// Returns a file descriptor that can be used to poll on new data.
+/// Can be passed to select/epoll to wait for data to become available.
+/// @param gpio Pointer to the BGpio struct.
+/// @param fd Output pointer to the file descriptor number.
+/// @return 0 on success, errno on error.
+int BGpio_getPollingFd(const BGpio* gpio, int* fd);
+
+/// Acknowledges the interrupt and resets the file descriptor.
+/// This must be called after each event triggers in order to be able to
+/// poll/select for another event.
+/// @param fd Polling file descriptor to reset.
+/// @return 0 on success, errno on error.
+int BGpio_ackInterruptEvent(int fd);
+
+/// Destroys a BGpio struct.
+/// @param gpio Pointer to the BGpio struct.
+void BGpio_delete(BGpio* gpio);
+
+/// @}
+
+__END_DECLS
+
+#endif  // SYSTEM_PERIPHERALMANAGER_GPIO_H_
diff --git a/peripheralmanager/include/peripheralmanager/i2c_device.h b/peripheralmanager/include/peripheralmanager/i2c_device.h
new file mode 100644
index 0000000..ca14477
--- /dev/null
+++ b/peripheralmanager/include/peripheralmanager/i2c_device.h
@@ -0,0 +1,121 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef SYSTEM_PERIPHERALMANAGER_I2C_DEVICE_H_
+#define SYSTEM_PERIPHERALMANAGER_I2C_DEVICE_H_
+
+#include <sys/cdefs.h>
+#include <sys/types.h>
+
+__BEGIN_DECLS
+
+/// @defgroup I2c I2c device interface
+/// @brief Functions to control an I2C device.
+///
+/// These functions can be used to control an I2C device.
+/// @{
+
+typedef struct BI2cDevice BI2cDevice;
+
+/// Reads from the device.
+/// @param device Pointer to the BI2cDevice struct.
+/// @param data Output buffer to write the data to.
+/// @param len Number of bytes to read.
+/// @param bytes_read Output pointer to the number of bytes actually read.
+/// @return 0 on success, errno on error
+int BI2cDevice_read(const BI2cDevice* device,
+                    void* data,
+                    uint32_t len,
+                    uint32_t* bytes_read);
+
+/// Reads a byte from an I2C register.
+/// @param device Pointer to the BI2cDevice struct.
+/// @param reg Register to read from.
+/// @param val Output pointer to value to read.
+/// @return 0 on success, errno on error
+int BI2cDevice_readRegByte(const BI2cDevice* device, uint8_t reg, uint8_t* val);
+
+/// Reads a word from an I2C register.
+/// @param device Pointer to the BI2cDevice struct.
+/// @param reg Register to read from.
+/// @param val Output pointer to value to read.
+/// @return 0 on success, errno on error
+int BI2cDevice_readRegWord(const BI2cDevice* device,
+                           uint8_t reg,
+                           uint16_t* val);
+
+/// Reads from an I2C register.
+/// @param device Pointer to the BI2cDevice struct.
+/// @param reg Register to read from.
+/// @param data Output buffer to write the data to.
+/// @param len Number of bytes to read.
+/// @param bytes_read Output pointer to the number of bytes read.
+/// @return 0 on success, errno on error
+int BI2cDevice_readRegBuffer(const BI2cDevice* device,
+                             uint8_t reg,
+                             void* data,
+                             uint32_t len,
+                             uint32_t* bytes_read);
+
+/// Writes to the device.
+/// @param device Pointer to the BI2cDevice struct.
+/// @param data Buffer to write.
+/// @param len Number of bytes to write.
+/// @param bytes_written Output pointer to the number of bytes written.
+/// @return 0 on success, errno on error
+int BI2cDevice_write(const BI2cDevice* device,
+                     const void* data,
+                     uint32_t len,
+                     uint32_t* bytes_written);
+
+/// Writes a byte to an I2C register.
+/// @param device Pointer to the BI2cDevice struct.
+/// @param reg Register to write to.
+/// @param val Value to write.
+/// @return 0 on success, errno on error
+int BI2cDevice_writeRegByte(const BI2cDevice* device, uint8_t reg, uint8_t val);
+
+/// Writes a word to an I2C register.
+/// @param device Pointer to the BI2cDevice struct.
+/// @param reg Register to write to.
+/// @param val Value to write.
+/// @return 0 on success, errno on error
+int BI2cDevice_writeRegWord(const BI2cDevice* device,
+                            uint8_t reg,
+                            uint16_t val);
+
+/// Writes to an I2C register.
+/// @param device Pointer to the BI2cDevice struct.
+/// @param reg Register to write to.
+/// @param data Data to write.
+/// @param len Number of bytes to write.
+/// @param bytes_written Output pointer to the number of bytes written.
+/// @return 0 on success, errno on error
+int BI2cDevice_writeRegBuffer(const BI2cDevice* device,
+                              uint8_t reg,
+                              const void* data,
+                              uint32_t len,
+                              uint32_t* bytes_written);
+
+/// Destroys a BI2cDevice struct.
+/// @param device Pointer to the BI2cDevice struct.
+void BI2cDevice_delete(BI2cDevice* device);
+
+/// @}
+
+__END_DECLS
+
+#endif  // SYSTEM_PERIPHERALMANAGER_I2C_DEVICE_H_
diff --git a/peripheralmanager/include/peripheralmanager/led.h b/peripheralmanager/include/peripheralmanager/led.h
new file mode 100644
index 0000000..c8cc19b
--- /dev/null
+++ b/peripheralmanager/include/peripheralmanager/led.h
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef SYSTEM_PERIPHERALMANAGER_LED_H_
+#define SYSTEM_PERIPHERALMANAGER_LED_H_
+
+#include <sys/cdefs.h>
+#include <sys/types.h>
+
+__BEGIN_DECLS
+
+/// @defgroup Led Led Interface
+/// @brief Functions to control onboard LEDs.
+///
+/// These functions can be used to query and control LEDs.
+/// @{
+
+typedef struct BLed BLed;
+
+/// Sets the LED brightness.
+/// @param led Pointer to the BLed object.
+/// @param brightness Brightness to set. If the brightness exceeds the maximum
+/// brightness supported, sets the maximum supported.
+/// @return 0 on success, errno on error.
+int BLed_setBrightness(const BLed* led, uint32_t brightness);
+
+/// Gets the LED brightness.
+/// @param led Pointer to the BLed object.
+/// @param brightness Output pointer to the current brightness.
+/// @return 0 on success, errno on error.
+int BLed_getBrightness(const BLed* led, uint32_t* brightness);
+
+/// Gets the LED max brightness.
+/// @param led Pointer to the BLed object.
+/// @param max_brightness Output pointer to the maximum brightness supported.
+/// @return 0 on success, errno on error.
+int BLed_getMaxBrightness(const BLed* led, uint32_t* max_brightness);
+
+/// Destroys a BLed object.
+/// @param led Pointer to the BLed object to destroy.
+void BLed_delete(BLed* led);
+
+/// @}
+
+__END_DECLS
+
+#endif  // SYSTEM_PERIPHERALMANAGER_LED_H_
diff --git a/peripheralmanager/include/peripheralmanager/peripheral_manager_client.h b/peripheralmanager/include/peripheralmanager/peripheral_manager_client.h
new file mode 100644
index 0000000..51821b0
--- /dev/null
+++ b/peripheralmanager/include/peripheralmanager/peripheral_manager_client.h
@@ -0,0 +1,143 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef SYSTEM_PERIPHERALMANAGER_PERIPHERAL_MANAGER_CLIENT_H_
+#define SYSTEM_PERIPHERALMANAGER_PERIPHERAL_MANAGER_CLIENT_H_
+
+#include <sys/cdefs.h>
+
+#include "peripheralmanager/gpio.h"
+#include "peripheralmanager/i2c_device.h"
+#include "peripheralmanager/led.h"
+#include "peripheralmanager/spi_device.h"
+#include "peripheralmanager/uart_device.h"
+
+__BEGIN_DECLS
+
+/// @defgroup PeripheralManagerClient Peripheral client functions
+/// @brief Functions to access embedded peripherals
+/// @{
+
+typedef struct BPeripheralManagerClient BPeripheralManagerClient;
+
+/// Returns the list of GPIOs.
+/// This does not take ownership into account.
+/// The list must be freed by the caller.
+/// @param client Pointer to the BPeripheralManagerClient struct.
+/// @param num_gpio Output pointer to the number of element in the list.
+/// @return The list of gpios.
+char** BPeripheralManagerClient_listGpio(const BPeripheralManagerClient* client,
+                                         int* num_gpio);
+
+/// Opens a GPIO and takes ownership of it.
+/// @param client Pointer to the BPeripheralManagerClient struct.
+/// @param name Name of the GPIO.
+/// @param gpio Output pointer to the BGpio struct. Empty on error.
+/// @return 0 on success, errno on error.
+int BPeripheralManagerClient_openGpio(const BPeripheralManagerClient* client,
+                                      const char* name,
+                                      BGpio** gpio);
+
+/// Returns the list of SPI buses.
+/// This does not take ownership into account.
+/// The list must be freed by the caller.
+/// @param client Pointer to the BPeripheralManagerClient struct.
+/// @param num_spi_buses Output pointer to the number of element in the list.
+/// @return The list of spi buses.
+char** BPeripheralManagerClient_listSpiBuses(
+    const BPeripheralManagerClient* client,
+    int* num_spi_buses);
+
+/// Opens a SPI device and takes ownership of it.
+/// @oaram client Pointer to the BPeripheralManagerClient struct.
+/// @param name Name of the SPI device.
+/// @param dev Output pointer to the BSpiDevice struct. Empty on error.
+/// @return 0 on success, errno on error.
+int BPeripheralManagerClient_openSpiDevice(
+    const BPeripheralManagerClient* client,
+    const char* name,
+    BSpiDevice** dev);
+
+/// Returns the list of LEDs available.
+/// @param client Pointer to the BPeripheralManagerClient struct.
+/// @param num_leds Output pointer to the number of leds.
+/// @return The list of LEDs. The list must be freed by the caller.
+char** BPeripheralManagerClient_listLeds(const BPeripheralManagerClient* client,
+                                         int* num_leds);
+
+/// Opens an LED and takes ownership of it.
+/// @oaram client Pointer to the BPeripheralManagerClient struct.
+/// @param name Name of the LED.
+/// @param dev Output pointer to the BLed struct. Empty on error.
+/// @return 0 on success, errno on error.
+int BPeripheralManagerClient_openLed(const BPeripheralManagerClient* client,
+                                     const char* name,
+                                     BLed** led);
+
+/// Returns the list of I2C buses.
+/// This does not take ownership into account.
+/// The list must be freed by the caller.
+/// @param client Pointer to the BPeripheralManagerClient struct.
+/// @param num_i2c_buses Output pointer to the number of element in the list.
+/// @return The list of i2c buses.
+char** BPeripheralManagerClient_listI2cBuses(
+    const BPeripheralManagerClient* client,
+    int* num_i2c_buses);
+
+/// Opens an I2C device and takes ownership of it.
+/// @param client Pointer to the BPeripheralManagerClient struct.
+/// @param name Name of the I2C bus.
+/// @param address Address of the I2C device.
+/// @param dev Output pointer to the BI2cDevice struct. Empty on error.
+/// @return 0 on success, errno on error
+int BPeripheralManagerClient_openI2cDevice(
+    const BPeripheralManagerClient* client,
+    const char* name,
+    uint32_t address,
+    BI2cDevice** dev);
+
+/// Returns the list of UART buses.
+/// This does not take ownership into account.
+/// The list must be freed by the caller.
+/// @param client Pointer to the BPeripheralManagerClient struct.
+/// @param num_uart_buses Output pointer to the number of element in the list.
+/// @return The list of uart buses.
+char** BPeripheralManagerClient_listUartDevices(
+    const BPeripheralManagerClient* client, int* num_uart_buses);
+
+/// Opens an UART device and takes ownership of it.
+/// @param client Pointer to the BPeripheralManagerClient struct.
+/// @param name Name of the UART device.
+/// @param dev Output pointer to the BUartDevice struct. Empty on error.
+/// @return 0 on success, errno on error
+int BPeripheralManagerClient_openUartDevice(
+    const BPeripheralManagerClient* client,
+    const char* name,
+    BUartDevice** dev);
+
+/// Creates a new client.
+/// @return A pointer to the created client. nullptr on errors.
+BPeripheralManagerClient* BPeripheralManagerClient_new();
+
+/// Destroys the peripheral manager client.
+/// @param client Pointer to the BPeripheralManagerClient struct.
+void BPeripheralManagerClient_delete(BPeripheralManagerClient* client);
+
+/// @}
+
+__END_DECLS
+
+#endif  //  SYSTEM_PERIPHERALMANAGER_PERIPHERAL_MANAGER_CLIENT_H_
diff --git a/peripheralmanager/include/peripheralmanager/spi_device.h b/peripheralmanager/include/peripheralmanager/spi_device.h
new file mode 100644
index 0000000..e81bdc1
--- /dev/null
+++ b/peripheralmanager/include/peripheralmanager/spi_device.h
@@ -0,0 +1,118 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef SYSTEM_PERIPHERALMANAGER_SPI_DEVICE_H_
+#define SYSTEM_PERIPHERALMANAGER_SPI_DEVICE_H_
+
+#include <sys/cdefs.h>
+#include <sys/types.h>
+
+__BEGIN_DECLS
+
+/// @defgroup Spi Spi device interface
+/// @brief Functions to control an SPI device.
+///
+/// These functions can be used to control an SPI device.
+/// @{
+
+/// Endianness.
+enum {
+  SPI_LSB_FIRST,  /**< Least significant bits first */
+  SPI_MSB_FIRST  /**< Most significant bits first */
+};
+
+/// SPI phase modes.
+enum {
+  SPI_CPHA = 0x01,  /**< Clock phase */
+  SPI_CPOL = 0x02  /**< Clock polarity */
+};
+
+/// SPI modes (similar to the Linux kernel's modes).
+enum {
+  SPI_MODE0 = 0,  /**< CPHA=0, CPOL=0 */
+  SPI_MODE1 = SPI_CPHA,  /**< CPHA=1, CPOL=0 */
+  SPI_MODE2 = SPI_CPOL,  /**< CPHA=0, CPOL=1 */
+  SPI_MODE3 = SPI_CPHA + SPI_CPOL  /**< CPHA=1, CPOL=1 */
+};
+
+typedef struct BSpiDevice BSpiDevice;
+
+/// Writes a byte to the device.
+/// @param device Pointer to the BSpiDevice struct.
+/// @param val Value to write.
+/// @return 0 on success, errno on error.
+int BSpiDevice_writeByte(const BSpiDevice* device, uint8_t val);
+
+/// Writes a buffer to the device.
+/// @param device Pointer to the BSpiDevice struct.
+/// @param data Buffer to write.
+/// @param len Length of the buffer.
+/// @return 0 on success, errno on error.
+int BSpiDevice_writeBuffer(const BSpiDevice* device,
+                           const void* data,
+                           size_t len);
+
+/// Transfer data to the device.
+/// @param device Pointer to the BSpiDevice struct.
+/// @param tx_data Buffer to write.
+/// @param rx_data Buffer to read data in. If NULL, no data will be read.
+/// @param len Length of the buffers.
+/// @return 0 on success, errno on error.
+int BSpiDevice_transfer(const BSpiDevice* device,
+                        const void* tx_data,
+                        void* rx_data,
+                        size_t len);
+
+/// Sets the frequency in Hertz.
+/// @param device Pointer to the BSpiDevice struct.
+/// @param freq_hz Frequency to set.
+/// @return 0 on success, errno on error.
+int BSpiDevice_setFrequency(const BSpiDevice* device, uint32_t freq_hz);
+
+/// Sets the SPI mode.
+/// @param device Pointer to the BSpiDevice struct.
+/// @param mode Mode to use. One of SPI_MODE0, SPI_MODE1, SPI_MODE2, SPI_MODE3.
+/// @return 0 on success, errno on error.
+int BSpiDevice_setMode(const BSpiDevice* device, int mode);
+
+/// Sets the bit justification.
+/// @param device Pointer to the BSpiDevice struct.
+/// @param bit_justification One of SPI_LSB_FIRST OR SPI_MSB_FIRST.
+/// @return 0 on success, errno on error.
+int BSpiDevice_setBitJustification(const BSpiDevice* device,
+                                   int bit_justification);
+
+/// Sets the number of bits per words.
+/// @param device Pointer to the BSpiDevice struct.
+/// @param bits_per_word Number of bits per word.
+/// @return 0 on success, errno on error.
+int BSpiDevice_setBitsPerWord(const BSpiDevice* device, uint8_t bits_per_word);
+
+/// Sets the delay to wait after each transfer.
+/// @param device Pointer to the BSpiDevice struct.
+/// @param delay_usecs Delay in microseconds.
+/// @return 0 on success, errno on error.
+int BSpiDevice_setDelay(const BSpiDevice* device, uint16_t delay_usecs);
+
+/// Destroys a BSpiDevice struct.
+/// @param device Pointer to the BSpiDevice struct.
+void BSpiDevice_delete(BSpiDevice* device);
+
+/// @}
+
+__END_DECLS
+
+#endif  // SYSTEM_PERIPHERALMANAGER_SPI_DEVICE_H_
diff --git a/peripheralmanager/include/peripheralmanager/uart_device.h b/peripheralmanager/include/peripheralmanager/uart_device.h
new file mode 100644
index 0000000..057a068
--- /dev/null
+++ b/peripheralmanager/include/peripheralmanager/uart_device.h
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef SYSTEM_PERIPHERALMANAGER_UART_DEVICE_H_
+#define SYSTEM_PERIPHERALMANAGER_UART_DEVICE_H_
+
+#include <sys/cdefs.h>
+#include <sys/types.h>
+
+__BEGIN_DECLS
+
+/// @defgroup Uart Uart device interface
+/// @brief Functions to control an UART device.
+///
+/// These functions can be used to control an UART device.
+/// @{
+
+typedef struct BUartDevice BUartDevice;
+
+/// Writes to a UART device.
+/// @param device Pointer to the BUartDevice struct.
+/// @param data Data to write.
+/// @param len Size of the data to write.
+/// @param bytes_written Output pointer to the number of bytes written.
+/// @return 0 on success, errno on error.
+int BUartDevice_write(const BUartDevice* device,
+                      const void* data,
+                      uint32_t len,
+                      uint32_t* bytes_written);
+
+/// Reads from a UART device.
+/// @param device Pointer to the BUartDevice struct.
+/// @param data Buffer to read the data into.
+/// @param len Number of bytes to read.
+/// @param bytes_read Output pointer to the number of bytes read.
+/// @return 0 on success, errno on error.
+int BUartDevice_read(const BUartDevice* device,
+                     void* data,
+                     uint32_t len,
+                     uint32_t* bytes_read);
+
+/// Sets the input and output speed of a UART device.
+/// @param device Pointer to the BUartDevice struct.
+/// @param device Uart device to configure.
+/// @param baudrate Speed in baud.
+/// @return 0 on success, errno on error.
+int BUartDevice_setBaudrate(const BUartDevice* device, uint32_t baudrate);
+
+/// Destroys a BUartDevice struct.
+/// @param device Pointer to the BUartDevice struct.
+void BUartDevice_delete(BUartDevice* device);
+
+/// @}
+
+__END_DECLS
+
+#endif  // SYSTEM_PERIPHERALMANAGER_UART_DEVICE_H_
diff --git a/peripheralmanager/ipc/Android.mk b/peripheralmanager/ipc/Android.mk
new file mode 100644
index 0000000..1d132fe
--- /dev/null
+++ b/peripheralmanager/ipc/Android.mk
@@ -0,0 +1,33 @@
+#
+# Copyright (C) 2015 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := libperipheralman_binder
+
+LOCAL_SHARED_LIBRARIES := libbinder
+LOCAL_EXPORT_SHARED_LIBRARY_HEADERS := libbinder
+
+LOCAL_SRC_FILES := \
+  android/os/IPeripheralManagerClient.aidl \
+  android/os/IPeripheralManager.aidl \
+
+LOCAL_SHARED_LIBRARIES := libbinder
+
+LOCAL_AIDL_INCLUDES := $(LOCAL_PATH)
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/peripheralmanager/ipc/android/os/IPeripheralManager.aidl b/peripheralmanager/ipc/android/os/IPeripheralManager.aidl
new file mode 100644
index 0000000..39f4c9b
--- /dev/null
+++ b/peripheralmanager/ipc/android/os/IPeripheralManager.aidl
@@ -0,0 +1,23 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.os;
+
+import android.os.IPeripheralManagerClient;
+
+interface IPeripheralManager {
+  IPeripheralManagerClient GetClient(IBinder lifeline);
+}
diff --git a/peripheralmanager/ipc/android/os/IPeripheralManagerClient.aidl b/peripheralmanager/ipc/android/os/IPeripheralManagerClient.aidl
new file mode 100644
index 0000000..98e1196
--- /dev/null
+++ b/peripheralmanager/ipc/android/os/IPeripheralManagerClient.aidl
@@ -0,0 +1,117 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.os;
+
+interface IPeripheralManagerClient {
+  // Gpio functions.
+  void ListGpio(out @utf8InCpp List<String> gpios);
+
+  void OpenGpio(@utf8InCpp String name);
+
+  void ReleaseGpio(@utf8InCpp String name);
+
+  void SetGpioEdge(@utf8InCpp String name, int type);
+
+  void SetGpioActiveType(@utf8InCpp String name, int type);
+
+  void SetGpioDirection(@utf8InCpp String name, int direction);
+
+  void SetGpioValue(@utf8InCpp String name, boolean value);
+
+  boolean GetGpioValue(@utf8InCpp String name);
+
+  FileDescriptor GetGpioPollingFd(@utf8InCpp String name);
+
+
+  // Spi functions.
+  void ListSpiBuses(out @utf8InCpp List<String> buses);
+
+  void OpenSpiDevice(@utf8InCpp String name);
+
+  void ReleaseSpiDevice(@utf8InCpp String name);
+
+  void SpiDeviceWriteByte(@utf8InCpp String name, byte data);
+
+  void SpiDeviceWriteBuffer(@utf8InCpp String name, in byte[] buffer);
+
+  void SpiDeviceTransfer(@utf8InCpp String name, in @nullable byte[] tx_data,
+                         out @nullable byte[] rx_data, int len);
+
+  void SpiDeviceSetFrequency(@utf8InCpp String name, int frequency_hz);
+
+  void SpiDeviceSetBitJustification(@utf8InCpp String name,
+                                    boolean lsb_first);
+
+  void SpiDeviceSetMode(@utf8InCpp String name, int mode);
+
+  void SpiDeviceSetBitsPerWord(@utf8InCpp String name, int nbits);
+
+  void SpiDeviceSetDelay(@utf8InCpp String name, int delay_usecs);
+
+
+  // Leds functions.
+  void ListLeds(out @utf8InCpp List<String> leds);
+
+  void OpenLed(@utf8InCpp String name);
+
+  void ReleaseLed(@utf8InCpp String name);
+
+  int LedGetBrightness(@utf8InCpp String name);
+
+  int LedGetMaxBrightness(@utf8InCpp String name);
+
+  void LedSetBrightness(@utf8InCpp String name, int brightness);
+
+
+  // I2c functions.
+  void ListI2cBuses(out @utf8InCpp List<String> buses);
+
+  void OpenI2cDevice(@utf8InCpp String name, int address);
+
+  void ReleaseI2cDevice(@utf8InCpp String name, int address);
+
+  int I2cRead(@utf8InCpp String name, int address, out byte[] data, int size);
+
+  int I2cReadRegByte(@utf8InCpp String name, int address, int reg);
+
+  int I2cReadRegWord(@utf8InCpp String name, int address, int reg);
+
+  int I2cReadRegBuffer(@utf8InCpp String name, int address, int reg,
+                       out byte[] data, int size);
+
+  int I2cWrite(@utf8InCpp String name, int address, in byte[] data);
+
+  void I2cWriteRegByte(@utf8InCpp String name, int address, int reg, byte val);
+
+  void I2cWriteRegWord(@utf8InCpp String name, int address, int reg, int val);
+
+  int I2cWriteRegBuffer(@utf8InCpp String name, int address, int reg,
+                        in byte[] data);
+
+  // Uart functions
+  void ListUartDevices(out @utf8InCpp List<String> devices);
+
+  void OpenUartDevice(@utf8InCpp String name);
+
+  void ReleaseUartDevice(@utf8InCpp String name);
+
+  void SetUartDeviceBaudrate(@utf8InCpp String name, int baudrate);
+
+  int UartDeviceWrite(@utf8InCpp String name, in byte[] data);
+
+  int UartDeviceRead(@utf8InCpp String name, out byte[] data, int size);
+}