diff options
author | Bertrand SIMONNET <bsimonnet@google.com> | 2016-03-23 10:20:14 -0700 |
---|---|---|
committer | Bertrand SIMONNET <bsimonnet@google.com> | 2016-03-23 11:08:25 -0700 |
commit | 6187530413fd184856f85ea09bd30040e5426422 (patch) | |
tree | f25d436a1d949de337c9552065c9f002e11955db | |
parent | ce91d9cc8081cf805ed75fd5598a51e2fac3d5ee (diff) | |
download | peripheralmanager-6187530413fd184856f85ea09bd30040e5426422.tar.gz |
Add unit tests for the Spi developer interfaces.
Bug: 27675223
Change-Id: I34289c5caa7ba7d5d1a1f419829830d3a221ead0
-rw-r--r-- | client/Android.mk | 1 | ||||
-rw-r--r-- | client/spi_unittest.cc | 193 | ||||
-rw-r--r-- | client/wrapper.cc | 12 | ||||
-rw-r--r-- | daemon/Android.mk | 4 | ||||
-rw-r--r-- | daemon/fake_devices.cc | 8 | ||||
-rw-r--r-- | daemon/fake_devices.h | 10 | ||||
-rw-r--r-- | daemon/spi_driver_spidev.cc | 7 | ||||
-rw-r--r-- | daemon/spi_manager.cc | 5 | ||||
-rw-r--r-- | daemon/spi_manager.h | 3 | ||||
-rw-r--r-- | daemon/spi_manager_unittest.cc | 12 | ||||
-rw-r--r-- | include/peripheralmanager/spi_device.h | 2 |
11 files changed, 238 insertions, 19 deletions
diff --git a/client/Android.mk b/client/Android.mk index cd47e7f..d8502f0 100644 --- a/client/Android.mk +++ b/client/Android.mk @@ -74,5 +74,6 @@ LOCAL_SRC_FILES := \ gpio_unittest.cc \ led_unittest.cc \ peripheral_manager_client_unittest.cc \ + spi_unittest.cc \ include $(BUILD_NATIVE_TEST) diff --git a/client/spi_unittest.cc b/client/spi_unittest.cc new file mode 100644 index 0000000..c8df86d --- /dev/null +++ b/client/spi_unittest.cc @@ -0,0 +1,193 @@ +/* + * 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 <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 ::testing::Test { + public: + void SetUp() { + pman_.InitForTest(); + 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: + PeripheralManager pman_; + 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)); + + 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; + ASSERT_EQ( + ENODEV, + BPeripheralManagerClient_openSpiDevice(client, "SPI_UNKOWN", &device)); + ASSERT_EQ(nullptr, device); + + BPeripheralManagerClient_delete(client); +} diff --git a/client/wrapper.cc b/client/wrapper.cc index cb13730..e6d9202 100644 --- a/client/wrapper.cc +++ b/client/wrapper.cc @@ -187,12 +187,20 @@ int BSpiDevice_setFrequency(const BSpiDevice* device, uint32_t freq_hz) { } int BSpiDevice_setMode(const BSpiDevice* device, int mode) { - return device->impl->SetMode(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) { - return device->impl->SetBitJustification(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) { diff --git a/daemon/Android.mk b/daemon/Android.mk index c8410da..7d10dc8 100644 --- a/daemon/Android.mk +++ b/daemon/Android.mk @@ -110,7 +110,9 @@ LOCAL_SHARED_LIBRARIES := \ libutils \ libhardware \ -LOCAL_SRC_FILES := $(libperipheralman_internal_CommonSources) +LOCAL_SRC_FILES := $(libperipheralman_internal_CommonSources) \ + fake_devices.cc \ + include $(BUILD_STATIC_LIBRARY) # peripheralman internals library for host tests diff --git a/daemon/fake_devices.cc b/daemon/fake_devices.cc index 20a4258..50d248e 100644 --- a/daemon/fake_devices.cc +++ b/daemon/fake_devices.cc @@ -48,4 +48,12 @@ 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/daemon/fake_devices.h b/daemon/fake_devices.h index 56d57a0..d1aa7f9 100644 --- a/daemon/fake_devices.h +++ b/daemon/fake_devices.h @@ -37,6 +37,14 @@ class FakeCharDevice : public CharDeviceInterface { 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_
\ No newline at end of file +#endif // SYSTEM_PERIPHERALMANAGER_DAEMON_FAKE_DEVICES_H_ diff --git a/daemon/spi_driver_spidev.cc b/daemon/spi_driver_spidev.cc index 55bb630..9a30b21 100644 --- a/daemon/spi_driver_spidev.cc +++ b/daemon/spi_driver_spidev.cc @@ -134,7 +134,7 @@ bool SpiDriverSpiDev::SetMode(SpiMode mode) { break; } - if (ioctl(fd_, SPI_IOC_WR_MODE, &k_mode) < 0) { + if (char_interface_->Ioctl(fd_, SPI_IOC_WR_MODE, &k_mode) < 0) { PLOG(ERROR) << "Failed to set mode"; return false; } @@ -144,7 +144,7 @@ bool SpiDriverSpiDev::SetMode(SpiMode mode) { bool SpiDriverSpiDev::SetBitJustification(bool lsb_first) { uint8_t k_lsb_first = lsb_first; - if (ioctl(fd_, SPI_IOC_WR_LSB_FIRST, &k_lsb_first) < 0) { + if (char_interface_->Ioctl(fd_, SPI_IOC_WR_LSB_FIRST, &k_lsb_first) < 0) { PLOG(ERROR) << "Failed to set bit justifcation"; return false; } @@ -152,7 +152,8 @@ bool SpiDriverSpiDev::SetBitJustification(bool lsb_first) { } bool SpiDriverSpiDev::SetBitsPerWord(uint8_t bits_per_word) { - if (ioctl(fd_, SPI_IOC_WR_BITS_PER_WORD, &bits_per_word) < 0) { + 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; } diff --git a/daemon/spi_manager.cc b/daemon/spi_manager.cc index 9e9dac8..4e11c84 100644 --- a/daemon/spi_manager.cc +++ b/daemon/spi_manager.cc @@ -34,6 +34,11 @@ SpiManager* SpiManager::GetSpiManager() { 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) { diff --git a/daemon/spi_manager.h b/daemon/spi_manager.h index f60e608..80c9d64 100644 --- a/daemon/spi_manager.h +++ b/daemon/spi_manager.h @@ -88,6 +88,9 @@ class 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. diff --git a/daemon/spi_manager_unittest.cc b/daemon/spi_manager_unittest.cc index 3dacbe5..924b014 100644 --- a/daemon/spi_manager_unittest.cc +++ b/daemon/spi_manager_unittest.cc @@ -24,16 +24,6 @@ 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() { @@ -74,4 +64,4 @@ TEST_F(SpiManagerTest, SetFrequency) { device->SetFrequency(100); } -} // namespace android
\ No newline at end of file +} // namespace android diff --git a/include/peripheralmanager/spi_device.h b/include/peripheralmanager/spi_device.h index b93b15e..e3392e2 100644 --- a/include/peripheralmanager/spi_device.h +++ b/include/peripheralmanager/spi_device.h @@ -67,7 +67,7 @@ int BSpiDevice_writeBuffer(const BSpiDevice* device, /// Transfer data to the device. /// @param device Pointer to the BSpiDevice struct. -/// @param tx_data Buffer to write. If NULL, no data will be written. +/// @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. |