| /* |
| * 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 "pin_mux_manager.h" |
| |
| #include <base/logging.h> |
| |
| namespace android { |
| |
| std::unique_ptr<PinMuxManager> g_pin_mux_manager; |
| |
| PinMuxManager::PinMuxManager() {} |
| |
| PinMuxManager::~PinMuxManager() {} |
| |
| // static |
| PinMuxManager* PinMuxManager::GetPinMuxManager() { |
| if (!g_pin_mux_manager) { |
| g_pin_mux_manager.reset(new PinMuxManager()); |
| } |
| return g_pin_mux_manager.get(); |
| } |
| |
| bool PinMuxManager::RegisterPin(std::string name, |
| bool gpio, |
| pin_mux_callbacks callbacks) { |
| if (pins_.count(name)) |
| return false; |
| pins_[name] = {false, gpio, callbacks}; |
| return true; |
| } |
| |
| bool PinMuxManager::RegisterPinGroup(std::string name, |
| std::set<std::string> pins) { |
| if (groups_.count(name)) |
| return false; |
| |
| // Check each pin is valid. |
| for (auto& p : pins) { |
| if (!pins_.count(p)) |
| return false; |
| } |
| groups_[name] = pins; |
| return true; |
| } |
| |
| bool PinMuxManager::RegisterSource(std::string name, |
| std::set<std::string> groups) { |
| if (sources_.count(name)) |
| return false; |
| |
| // Check each group is valid. |
| for (auto& g : groups) { |
| if (!groups_.count(g)) |
| return false; |
| } |
| sources_[name] = groups; |
| return true; |
| } |
| |
| bool PinMuxManager::RegisterSimpleSource(std::string name, |
| std::set<std::string> pins) { |
| if (!RegisterPinGroup(name, pins)) |
| return false; |
| if (!RegisterSource(name, {name})) { |
| // TODO(leecam): Unregister Group |
| return false; |
| } |
| return true; |
| } |
| |
| bool PinMuxManager::SetSource(std::string name, std::string group) { |
| if (!sources_.count(name)) |
| return false; |
| |
| if (!sources_[name].count(group)) |
| return false; |
| |
| // Check to make sure each pin is not in use. |
| for (auto& p : groups_[group]) { |
| if (pins_[p].in_use) |
| return false; |
| } |
| |
| // Enable each Pin |
| for (auto& p : groups_[group]) { |
| pins_[p].in_use = true; |
| |
| // TODO(leecam): Handle failures here!!! |
| if (pins_[p].callbacks.mux_cb) |
| pins_[p].callbacks.mux_cb(p.c_str(), name.c_str()); |
| } |
| |
| return true; |
| } |
| |
| void PinMuxManager::ReleaseSource(std::string name, std::string group) { |
| if (!sources_.count(name)) |
| return; |
| if (!sources_[name].count(group)) |
| return; |
| for (auto& p : groups_[group]) { |
| if (!pins_[p].in_use) { |
| LOG(WARNING) << "Releasig Pin " << p << " that is not in use."; |
| } |
| pins_[p].in_use = false; |
| } |
| } |
| |
| bool PinMuxManager::SetSimpleSource(std::string name) { |
| return SetSource(name, name); |
| } |
| |
| bool PinMuxManager::SetGpio(std::string name) { |
| if (!pins_.count(name)) { |
| LOG(WARNING) << "PinMuxManager: Pin not found " << name; |
| return false; |
| } |
| if (pins_[name].in_use) { |
| LOG(WARNING) << "PinMuxManager: Pin in use " << name; |
| return false; |
| } |
| if (pins_[name].callbacks.mux_cb) { |
| if (!pins_[name].callbacks.mux_cb(name.c_str(), nullptr)) |
| return false; |
| } |
| pins_[name].in_use = true; |
| return true; |
| } |
| |
| void PinMuxManager::ReleaseGpio(std::string name) { |
| if (!pins_.count(name)) |
| return; |
| pins_[name].in_use = false; |
| } |
| |
| bool PinMuxManager::SetGpioDirection(std::string name, bool output) { |
| if (!pins_.count(name)) { |
| LOG(WARNING) << "SetGpioDirection pin not found " << name; |
| return false; |
| } |
| // Check if not in use - this should maybe be a DCHECK as |
| // it shoudn't be able to happen. |
| if (!pins_[name].in_use) { |
| LOG(WARNING) << "SetGpioDirection not in use " << name; |
| return false; |
| } |
| if (pins_[name].callbacks.direction_cb) |
| return pins_[name].callbacks.direction_cb(name.c_str(), output); |
| |
| return true; |
| } |
| |
| } // namespace android |