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);
+}