diff options
author | Lee Campbell <leecam@google.com> | 2016-03-02 17:43:08 -0800 |
---|---|---|
committer | Lee Campbell <leecam@google.com> | 2016-03-03 20:06:29 +0000 |
commit | cee92931cbe24efa9348d14a126bf70f811091c3 (patch) | |
tree | 4226f923c7c9473b71977aab9f7d12c660bff55d | |
parent | f866d3a310074b5e7e5ca491d676a562d7d3bde2 (diff) | |
download | peripheralmanager-cee92931cbe24efa9348d14a126bf70f811091c3.tar.gz |
Adding bare bones SPI driver
Add support for a spidev driver.
Ioctls are not wired up yet.
BUG: 26779252
Change-Id: I8d81d685077798ae96e73d0061b8f44c94d30310
-rw-r--r-- | daemon/Android.mk | 2 | ||||
-rw-r--r-- | daemon/peripheral_manager.cc | 2 | ||||
-rw-r--r-- | daemon/spi_driver.h | 70 | ||||
-rw-r--r-- | daemon/spi_driver_spidev.cc | 99 | ||||
-rw-r--r-- | daemon/spi_driver_spidev.h | 60 |
5 files changed, 232 insertions, 1 deletions
diff --git a/daemon/Android.mk b/daemon/Android.mk index 3689d38..c3dac65 100644 --- a/daemon/Android.mk +++ b/daemon/Android.mk @@ -76,6 +76,7 @@ LOCAL_SRC_FILES := \ peripheral_manager.cc \ peripheral_manager_client.cc \ pin_mux_manager.cc \ + spi_driver_spidev.cc \ include $(BUILD_STATIC_LIBRARY) @@ -97,6 +98,7 @@ LOCAL_SRC_FILES := \ gpio_driver_sysfs.cc \ gpio_manager.cc \ pin_mux_manager.cc \ + spi_driver_spidev.cc \ include $(BUILD_HOST_STATIC_LIBRARY) diff --git a/daemon/peripheral_manager.cc b/daemon/peripheral_manager.cc index 758b48b..cf7476e 100644 --- a/daemon/peripheral_manager.cc +++ b/daemon/peripheral_manager.cc @@ -110,7 +110,7 @@ bool PeripheralManager::RegisterDrivers() { bool PeripheralManager::InitHal() { const hw_module_t* module = nullptr; if (hw_get_module(PERIPHERAL_IO_HARDWARE_MODULE_ID, &module) != 0) { - LOG(INFO) << "Failed to load HAL" << module; + LOG(ERROR) << "Failed to load HAL" << module; return false; } diff --git a/daemon/spi_driver.h b/daemon/spi_driver.h new file mode 100644 index 0000000..6d7bb65 --- /dev/null +++ b/daemon/spi_driver.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_SPI_DRIVER_H_ +#define SYSTEM_PERIPHERALMANAGER_DAEMON_SPI_DRIVER_H_ + +#include <stdint.h> + +#include <memory> +#include <string> + +#include <base/macros.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(int mode) = 0; + virtual bool SetBitJustification(bool lsb_first) = 0; + virtual bool SetBitsPerWord(uint32_t bits_per_word) = 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: + 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/daemon/spi_driver_spidev.cc b/daemon/spi_driver_spidev.cc new file mode 100644 index 0000000..9d8d3b0 --- /dev/null +++ b/daemon/spi_driver_spidev.cc @@ -0,0 +1,99 @@ +/* + * 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; + return true; +} + +// TODO(leecam): Wire up these IOCTLs once the client code lands. +bool SpiDriverSpiDev::Transfer(const void* tx_data, void* rx_data, size_t len) { + LOG(INFO) << "SPI Transfer"; + 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 (char_interface_->Ioctl(fd_, SPI_IOC_RD_MAX_SPEED_HZ, &max_speed) != 0) + return false; + if (speed_hz > max_speed) + speed_hz = max_speed; + + speed_hz_ = speed_hz; + return true; +} + +bool SpiDriverSpiDev::SetMode(int mode) { + return true; +} + +bool SpiDriverSpiDev::SetBitJustification(bool lsb_first) { + return true; +} + +bool SpiDriverSpiDev::SetBitsPerWord(uint32_t bits_per_word) { + return true; +} + +} // namespace android
\ No newline at end of file diff --git a/daemon/spi_driver_spidev.h b/daemon/spi_driver_spidev.h new file mode 100644 index 0000000..f422ac3 --- /dev/null +++ b/daemon/spi_driver_spidev.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_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: + 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(int mode) override; + bool SetBitJustification(bool lsb_first) override; + bool SetBitsPerWord(uint32_t bits_per_word) override; + + private: + int fd_; + uint32_t bits_per_word_; + uint32_t speed_hz_; + 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_ |