aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLee Campbell <leecam@google.com>2016-03-08 16:00:55 -0800
committerLee Campbell <leecam@google.com>2016-03-08 17:07:56 -0800
commitc589f9dc35abbd00601d50f732a4d7e0c83dccc1 (patch)
tree1a5d47d9d03b6ca294bc0258291dc17c6edf77a8
parente1adeba7ee43e6c609655c764d5dc8a7748d0126 (diff)
downloadperipheralmanager-c589f9dc35abbd00601d50f732a4d7e0c83dccc1.tar.gz
Hook up the SPI HAL to the SPI manager
Implement the backend IOCTLS for SPI BUG: 27555414 Change-Id: I4be6b9e33dd7b6d2483a04f368289a3229df0439 TEST: Tested with an RGB led
-rw-r--r--client/wrapper.cc2
-rw-r--r--daemon/peripheral_manager.cc40
-rw-r--r--daemon/spi_driver.h2
-rw-r--r--daemon/spi_driver_spidev.cc72
-rw-r--r--daemon/spi_driver_spidev.h4
-rw-r--r--daemon/spi_manager.h2
-rw-r--r--example/Android.mk18
-rw-r--r--example/pio_flash_apa10c.cc82
-rw-r--r--hal/hardware/peripheral_io.h6
-rw-r--r--include/peripheralmanager/spi_device.h2
10 files changed, 214 insertions, 16 deletions
diff --git a/client/wrapper.cc b/client/wrapper.cc
index 03f7e02..1ac11d4 100644
--- a/client/wrapper.cc
+++ b/client/wrapper.cc
@@ -144,7 +144,7 @@ int BSpiDevice_setBitJustification(const BSpiDevice* device,
}
int BSpiDevice_setBitsPerWord(const BSpiDevice* device,
- uint32_t bits_per_word) {
+ uint8_t bits_per_word) {
return device->impl->SetBitsPerWord(bits_per_word);
}
diff --git a/daemon/peripheral_manager.cc b/daemon/peripheral_manager.cc
index 0ab602d..2a1e038 100644
--- a/daemon/peripheral_manager.cc
+++ b/daemon/peripheral_manager.cc
@@ -24,6 +24,7 @@
#include "gpio_driver_sysfs.h"
#include "gpio_manager.h"
#include "pin_mux_manager.h"
+#include "spi_driver_spidev.h"
namespace android {
namespace {
@@ -37,6 +38,15 @@ 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);
+}
+
// Pin Mux callbacks.
static int RegisterPin(const char* name,
int gpio,
@@ -58,7 +68,9 @@ static int RegisterSource(const char* name, char** groups, size_t nr_groups) {
return PinMuxManager::GetPinMuxManager()->RegisterSource(name, groups_set);
}
-static int RegisterSimpleSource(const char* name, char** pins, size_t nr_pins) {
+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]);
@@ -73,7 +85,7 @@ PeripheralManager::PeripheralManager() {}
PeripheralManager::~PeripheralManager() = default;
bool PeripheralManager::Init() {
- if(!RegisterDrivers())
+ if (!RegisterDrivers())
return false;
if (!InitHal())
@@ -101,10 +113,20 @@ void PeripheralManager::binderDied(const wp<IBinder>& who) {
}
bool PeripheralManager::RegisterDrivers() {
- // Register GPIO Sysfs driver.
- return GpioManager::GetGpioManager()->RegisterDriver(
- std::unique_ptr<GpioDriverInfoBase>(
- new GpioDriverInfo<GpioDriverSysfs, void*>(nullptr)));
+ if (!SpiManager::GetSpiManager()->RegisterDriver(
+ std::unique_ptr<SpiDriverInfoBase>(
+ new SpiDriverInfo<SpiDriverSpiDev, CharDeviceFactory*>(
+ nullptr)))) {
+ LOG(ERROR) << "Failed to load driver: SpiDriverSpiDev";
+ return false;
+ }
+ if (!GpioManager::GetGpioManager()->RegisterDriver(
+ std::unique_ptr<GpioDriverInfoBase>(
+ new GpioDriverInfo<GpioDriverSysfs, void*>(nullptr)))) {
+ LOG(ERROR) << "Failed to load driver: GpioDriverSysfs";
+ return false;
+ }
+ return true;
}
bool PeripheralManager::InitHal() {
@@ -118,9 +140,15 @@ bool PeripheralManager::InitHal() {
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,
+
+ // Pin Mux
.register_pin = RegisterPin,
.register_pin_group = RegisterPinGroup,
.register_source = RegisterSource,
diff --git a/daemon/spi_driver.h b/daemon/spi_driver.h
index 9894886..3f04e36 100644
--- a/daemon/spi_driver.h
+++ b/daemon/spi_driver.h
@@ -39,7 +39,7 @@ class SpiDriverInterface {
virtual bool SetFrequency(uint32_t speed_hz) = 0;
virtual bool SetMode(SpiMode mode) = 0;
virtual bool SetBitJustification(bool lsb_first) = 0;
- virtual bool SetBitsPerWord(uint32_t bits_per_word) = 0;
+ virtual bool SetBitsPerWord(uint8_t bits_per_word) = 0;
};
class SpiDriverInfoBase {
diff --git a/daemon/spi_driver_spidev.cc b/daemon/spi_driver_spidev.cc
index 7870b84..55bb630 100644
--- a/daemon/spi_driver_spidev.cc
+++ b/daemon/spi_driver_spidev.cc
@@ -61,12 +61,37 @@ bool SpiDriverSpiDev::Init(uint32_t bus_id, uint32_t cs) {
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 8 bits per word.
+ bits_per_word_ = 8;
+
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";
+ 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 = 0;
+ msg.len = len;
+
+ if (char_interface_->Ioctl(fd_, SPI_IOC_MESSAGE(1), &msg) < 0) {
+ PLOG(ERROR) << "SPI Transfer IOCTL Failed";
+ return false;
+ }
return true;
}
@@ -75,7 +100,7 @@ bool SpiDriverSpiDev::SetFrequency(uint32_t speed_hz) {
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)
+ if (!GetMaxFrequency(&max_speed))
return false;
if (speed_hz > max_speed)
speed_hz = max_speed;
@@ -84,15 +109,54 @@ bool SpiDriverSpiDev::SetFrequency(uint32_t 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 (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 (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(uint32_t bits_per_word) {
+bool SpiDriverSpiDev::SetBitsPerWord(uint8_t bits_per_word) {
+ if (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;
}
diff --git a/daemon/spi_driver_spidev.h b/daemon/spi_driver_spidev.h
index 6dfc0d1..1214e2b 100644
--- a/daemon/spi_driver_spidev.h
+++ b/daemon/spi_driver_spidev.h
@@ -40,9 +40,11 @@ class SpiDriverSpiDev : public SpiDriverInterface {
bool SetFrequency(uint32_t speed_hz) override;
bool SetMode(SpiMode mode) override;
bool SetBitJustification(bool lsb_first) override;
- bool SetBitsPerWord(uint32_t bits_per_word) override;
+ bool SetBitsPerWord(uint8_t bits_per_word) override;
private:
+ bool GetMaxFrequency(uint32_t* max_freq);
+
int fd_;
uint32_t bits_per_word_;
uint32_t speed_hz_;
diff --git a/daemon/spi_manager.h b/daemon/spi_manager.h
index 6c3c3fb..92fc9ac 100644
--- a/daemon/spi_manager.h
+++ b/daemon/spi_manager.h
@@ -72,7 +72,7 @@ class SpiDevice {
return bus_->driver_->SetBitJustification(lsb_first);
}
- bool SetBitsPerWord(uint32_t bits_per_word) {
+ bool SetBitsPerWord(uint8_t bits_per_word) {
return bus_->driver_->SetBitsPerWord(bits_per_word);
}
diff --git a/example/Android.mk b/example/Android.mk
index 82a1a6e..c3e1ddd 100644
--- a/example/Android.mk
+++ b/example/Android.mk
@@ -36,3 +36,21 @@ LOCAL_SRC_FILES := \
peripheralmanager_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 := \
+ libbinder \
+ libbinderwrapper \
+ libbrillo \
+ libchrome \
+ libperipheralman \
+ libutils \
+
+LOCAL_SRC_FILES := \
+ pio_flash_apa10c.cc \
+
+include $(BUILD_EXECUTABLE)
diff --git a/example/pio_flash_apa10c.cc b/example/pio_flash_apa10c.cc
new file mode 100644
index 0000000..68abc49
--- /dev/null
+++ b/example/pio_flash_apa10c.cc
@@ -0,0 +1,82 @@
+/*
+ * 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/at_exit.h>
+#include <base/logging.h>
+#include <base/message_loop/message_loop.h>
+#include <base/sys_info.h>
+#include <base/time/time.h>
+#include <binderwrapper/binder_wrapper.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());
+ android::BinderWrapper::Create();
+
+ 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;
+ if (BPeripheralManagerClient_openSpiDevice(client, "SPI2", &my_spi) !=
+ PERIPHERAL_IO_OK) {
+ LOG(ERROR) << "Failed to open Spi";
+ 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/hal/hardware/peripheral_io.h b/hal/hardware/peripheral_io.h
index d08898b..1aa44d5 100644
--- a/hal/hardware/peripheral_io.h
+++ b/hal/hardware/peripheral_io.h
@@ -54,12 +54,16 @@ typedef struct peripheral_registration_cb_t {
int (*register_pin)(const char* name, int gpio, pin_mux_callbacks callbacks);
int (*register_pin_group)(const char* name, char** pins, size_t nr_pins);
int (*register_source)(const char* name, char** groups, size_t nr_groups);
- int (*register_simple_source)(const char* name, char** pins, size_t nr_pins);
+ int (*register_simple_source)(const char* name, const char** pins, size_t nr_pins);
// Gpio functions.
int (*register_gpio_sysfs)(const char* name, uint32_t index);
int (*set_gpio_pin_mux)(const char* name, const char* source);
+ // Spi functions.
+ int (*register_spi_dev_bus)(const char* name, uint32_t bus, uint32_t cs);
+ int (*set_spi_pin_mux)(const char* name, const char* source);
+
} peripheral_registration_cb_t;
typedef struct peripheral_io_module_t peripheral_io_module_t;
diff --git a/include/peripheralmanager/spi_device.h b/include/peripheralmanager/spi_device.h
index 3c65d28..631dae6 100644
--- a/include/peripheralmanager/spi_device.h
+++ b/include/peripheralmanager/spi_device.h
@@ -99,7 +99,7 @@ int BSpiDevice_setBitJustification(const BSpiDevice* device,
/// @param device Pointer to the BSpiDevice struct.
/// @param bits_per_word Number of bits per word.
/// @return Error code.
-int BSpiDevice_setBitsPerWord(const BSpiDevice* device, uint32_t bits_per_word);
+int BSpiDevice_setBitsPerWord(const BSpiDevice* device, uint8_t bits_per_word);
/// Destroys a BSpiDevice struct.
/// @param device Pointer to the BSpiDevice struct.