diff options
Diffstat (limited to 'daemon')
-rw-r--r-- | daemon/Android.mk | 6 | ||||
-rw-r--r-- | daemon/fake_devices.cc | 51 | ||||
-rw-r--r-- | daemon/fake_devices.h | 42 | ||||
-rw-r--r-- | daemon/spi_manager.cc | 115 | ||||
-rw-r--r-- | daemon/spi_manager.h | 116 | ||||
-rw-r--r-- | daemon/spi_manager_unittest.cc | 77 |
6 files changed, 407 insertions, 0 deletions
diff --git a/daemon/Android.mk b/daemon/Android.mk index c3dac65..9e5e79e 100644 --- a/daemon/Android.mk +++ b/daemon/Android.mk @@ -71,12 +71,14 @@ LOCAL_SHARED_LIBRARIES := \ $(peripheralman_CommonSharedLibraries) \ LOCAL_SRC_FILES := \ + char_device.cc \ gpio_driver_sysfs.cc \ gpio_manager.cc \ peripheral_manager.cc \ peripheral_manager_client.cc \ pin_mux_manager.cc \ spi_driver_spidev.cc \ + spi_manager.cc \ include $(BUILD_STATIC_LIBRARY) @@ -95,10 +97,12 @@ LOCAL_STATIC_LIBRARIES := \ peripheral_manager_hal_headers \ LOCAL_SRC_FILES := \ + char_device.cc \ gpio_driver_sysfs.cc \ gpio_manager.cc \ pin_mux_manager.cc \ spi_driver_spidev.cc \ + spi_manager.cc \ include $(BUILD_HOST_STATIC_LIBRARY) @@ -117,7 +121,9 @@ LOCAL_SHARED_LIBRARIES := \ libchrome \ LOCAL_SRC_FILES := \ + fake_devices.cc \ gpio_manager_unittest.cc \ pin_mux_manager_unittest.cc \ + spi_manager_unittest.cc \ include $(BUILD_HOST_NATIVE_TEST) diff --git a/daemon/fake_devices.cc b/daemon/fake_devices.cc new file mode 100644 index 0000000..20a4258 --- /dev/null +++ b/daemon/fake_devices.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 "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 0; +} + +ssize_t FakeCharDevice::Write(int fd, const void* buf, size_t count) { + return 0; +} + +int FakeCharDevice::Poll(struct pollfd* fds, nfds_t nfds, int timeout) { + return 0; +} + +} // namespace android diff --git a/daemon/fake_devices.h b/daemon/fake_devices.h new file mode 100644 index 0000000..56d57a0 --- /dev/null +++ b/daemon/fake_devices.h @@ -0,0 +1,42 @@ +/* + * 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; +}; + +} // namespace android + +#endif // SYSTEM_PERIPHERALMANAGER_DAEMON_FAKE_DEVICES_H_
\ No newline at end of file diff --git a/daemon/spi_manager.cc b/daemon/spi_manager.cc new file mode 100644 index 0000000..3afb45c --- /dev/null +++ b/daemon/spi_manager.cc @@ -0,0 +1,115 @@ +/* + * 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(); +} + +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::GetSpiDevBusses() { + std::vector<std::string> buses; + for (auto& i : spidev_buses_) + buses.push_back(i.first); + return buses; +} + +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/daemon/spi_manager.h b/daemon/spi_manager.h new file mode 100644 index 0000000..609f38e --- /dev/null +++ b/daemon/spi_manager.h @@ -0,0 +1,116 @@ +/* + * 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 "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: + 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(int mode) { return bus_->driver_->SetMode(mode); } + + bool SetBitJustification(bool lsb_first) { + return bus_->driver_->SetBitJustification(lsb_first); + } + + bool SetBitsPerWord(uint32_t bits_per_word) { + return bus_->driver_->SetBitsPerWord(bits_per_word); + } + + private: + SpiDevBus* bus_; +}; + +class SpiManager { + public: + friend class SpiManagerTest; + ~SpiManager(); + + // Get the singleton. + static SpiManager* GetSpiManager(); + + // 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> GetSpiDevBusses(); + + 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/daemon/spi_manager_unittest.cc b/daemon/spi_manager_unittest.cc new file mode 100644 index 0000000..51da825 --- /dev/null +++ b/daemon/spi_manager_unittest.cc @@ -0,0 +1,77 @@ +/* + * 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 FakeDeviceFactory : public CharDeviceFactory { + public: + FakeDeviceFactory() {} + ~FakeDeviceFactory(){}; + + std::unique_ptr<CharDeviceInterface> NewCharDevice() override { + return std::unique_ptr<CharDeviceInterface>(new FakeCharDevice()); + } +}; + +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.GetSpiDevBusses(); + 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
\ No newline at end of file |