debug!("node activated bits updated:{:#06b}.", new_state);
let led = new_state != 0;
- self.power_controller.power_led(led).await?;
+ if let Err(e) = self.power_controller.power_led(led).await {
+ log::warn!("power LED error: {}", e);
+ }
// also update the actual power state accordingly
self.power_controller
// See the License for the specific language governing permissions and
// limitations under the License.
use humantime::format_duration;
-use std::str::Utf8Error;
+use std::{fmt::Display, str::Utf8Error};
use thiserror::Error;
use tokio::time::Instant;
}
}
-impl ToString for SchemedAuthError {
- fn to_string(&self) -> String {
- self.1.to_string()
+impl Display for SchemedAuthError {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ write!(f, "{}", self.1)
}
}
pub const NODE3_USBOTG_DEV: u32 = 10;
pub const NODE4_USBOTG_DEV: u32 = 14;
-pub const PORT1_EN: u32 = 0;
-pub const PORT2_EN: u32 = 4;
-pub const PORT3_EN: u32 = 8;
-pub const PORT4_EN: u32 = 12;
-
pub const PORT1_RPIBOOT: u32 = 3;
pub const PORT2_RPIBOOT: u32 = 7;
pub const PORT3_RPIBOOT: u32 = 11;
// 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.
+use std::collections::HashMap;
const NODE_COUNT: u8 = 4;
/// small helper macro which handles the code duplication of declaring gpio lines.
(mask != 0).then_some((n as usize, state))
})
}
+
+pub fn load_lines(chip: &gpiod::Chip) -> HashMap<String, gpiod::LineId> {
+ HashMap::from_iter((0..chip.num_lines()).filter_map(|i| {
+ chip.line_info(i)
+ .ok()
+ .map(|info| (info.name, i as gpiod::LineId))
+ }))
+}
// 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.
-use super::{gpio_definitions::*, helpers::bit_iterator, NodeId};
+use super::{
+ helpers::{bit_iterator, load_lines},
+ NodeId,
+};
use crate::gpio_output_array;
use anyhow::Context;
use gpiod::{Chip, Lines, Output};
use std::time::Duration;
use tokio::time::sleep;
+const PORT1_EN: &str = "node1-en";
+const PORT2_EN: &str = "node2-en";
+const PORT3_EN: &str = "node3-en";
+const PORT4_EN: &str = "node4-en";
+
// This structure is a thin layer that abstracts away the interaction details
// with Linux's power subsystem.
pub struct PowerController {
impl PowerController {
pub fn new() -> anyhow::Result<Self> {
let chip1 = Chip::new("/dev/gpiochip1").context("gpiod chip1")?;
- let enable = gpio_output_array!(chip1, PORT1_EN, PORT2_EN, PORT3_EN, PORT4_EN);
+ let lines = load_lines(&chip1);
+ let port1 = *lines
+ .get(PORT1_EN)
+ .ok_or(anyhow::anyhow!("cannot find PORT1_EN"))?;
+ let port2 = *lines
+ .get(PORT2_EN)
+ .ok_or(anyhow::anyhow!("cannot find PORT2_EN"))?;
+ let port3 = *lines
+ .get(PORT3_EN)
+ .ok_or(anyhow::anyhow!("cannot find PORT3_EN"))?;
+ let port4 = *lines
+ .get(PORT4_EN)
+ .ok_or(anyhow::anyhow!("cannot find PORT4_EN"))?;
+
+ let enable = gpio_output_array!(chip1, port1, port2, port3, port4);
Ok(PowerController { enable })
}
Ok(())
}
- pub async fn power_led(&self, on: bool) -> std::io::Result<()> {
+ pub async fn power_led(&self, on: bool) -> anyhow::Result<()> {
const SYS_LED: &str = "/sys/class/leds/fp:sys/brightness";
- tokio::fs::write(SYS_LED, if on { "1" } else { "0" }).await
+ tokio::fs::write(SYS_LED, if on { "1" } else { "0" })
+ .await
+ .context(SYS_LED)
}
}
#[post("/serial/status")]
async fn serial_status(serials: web::Data<SerialConnections>) -> impl Responder {
- serde_json::to_string(&serials.get_state()).map_or_else(|e| e.to_string(), |s| s)
+ serde_json::to_string(&serials.get_state()).unwrap_or_else(|e| e.to_string())
}
pub async fn legacy_serial_set_handler(