aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBertrand SIMONNET <bsimonnet@google.com>2016-03-23 10:20:14 -0700
committerBertrand SIMONNET <bsimonnet@google.com>2016-03-23 11:08:25 -0700
commit6187530413fd184856f85ea09bd30040e5426422 (patch)
treef25d436a1d949de337c9552065c9f002e11955db
parentce91d9cc8081cf805ed75fd5598a51e2fac3d5ee (diff)
downloadperipheralmanager-6187530413fd184856f85ea09bd30040e5426422.tar.gz
Add unit tests for the Spi developer interfaces.
Bug: 27675223 Change-Id: I34289c5caa7ba7d5d1a1f419829830d3a221ead0
-rw-r--r--client/Android.mk1
-rw-r--r--client/spi_unittest.cc193
-rw-r--r--client/wrapper.cc12
-rw-r--r--daemon/Android.mk4
-rw-r--r--daemon/fake_devices.cc8
-rw-r--r--daemon/fake_devices.h10
-rw-r--r--daemon/spi_driver_spidev.cc7
-rw-r--r--daemon/spi_manager.cc5
-rw-r--r--daemon/spi_manager.h3
-rw-r--r--daemon/spi_manager_unittest.cc12
-rw-r--r--include/peripheralmanager/spi_device.h2
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.