Skip to content

Commit f621974

Browse files
authored
Merge pull request #21 from hnez/usb-hub-state
usb_hub: split powered state and request to prevent glitches
2 parents c6af4b8 + a68ec32 commit f621974

File tree

2 files changed

+31
-16
lines changed

2 files changed

+31
-16
lines changed

src/ui/screens/usb.rs

Lines changed: 20 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,8 @@ impl UsbScreen {
5151

5252
struct Active {
5353
widgets: WidgetContainer,
54-
port_enables: [Arc<Topic<bool>>; 3],
54+
port_requests: [Arc<Topic<bool>>; 3],
55+
port_states: [Arc<Topic<bool>>; 3],
5556
highlighted: Arc<Topic<usize>>,
5657
}
5758

@@ -78,19 +79,19 @@ impl ActivatableScreen for UsbScreen {
7879
(
7980
0,
8081
"Port 1",
81-
&ui.res.usb_hub.port1.powered,
82+
&ui.res.usb_hub.port1.status,
8283
&ui.res.adc.usb_host1_curr.topic,
8384
),
8485
(
8586
1,
8687
"Port 2",
87-
&ui.res.usb_hub.port2.powered,
88+
&ui.res.usb_hub.port2.status,
8889
&ui.res.adc.usb_host2_curr.topic,
8990
),
9091
(
9192
2,
9293
"Port 3",
93-
&ui.res.usb_hub.port3.powered,
94+
&ui.res.usb_hub.port3.status,
9495
&ui.res.adc.usb_host3_curr.topic,
9596
),
9697
];
@@ -147,16 +148,22 @@ impl ActivatableScreen for UsbScreen {
147148
});
148149
}
149150

150-
let port_enables = [
151-
ui.res.usb_hub.port1.powered.clone(),
152-
ui.res.usb_hub.port2.powered.clone(),
153-
ui.res.usb_hub.port3.powered.clone(),
151+
let port_requests = [
152+
ui.res.usb_hub.port1.request.clone(),
153+
ui.res.usb_hub.port2.request.clone(),
154+
ui.res.usb_hub.port3.request.clone(),
155+
];
156+
let port_states = [
157+
ui.res.usb_hub.port1.status.clone(),
158+
ui.res.usb_hub.port2.status.clone(),
159+
ui.res.usb_hub.port3.status.clone(),
154160
];
155161
let highlighted = self.highlighted.clone();
156162

157163
let active = Active {
158164
widgets,
159-
port_enables,
165+
port_requests,
166+
port_states,
160167
highlighted,
161168
};
162169

@@ -182,7 +189,10 @@ impl ActiveScreen for Active {
182189
InputEvent::ToggleAction(_) => {
183190
self.highlighted.set((highlighted + 1) % 3);
184191
}
185-
InputEvent::PerformAction(_) => self.port_enables[highlighted].toggle(false),
192+
InputEvent::PerformAction(_) => {
193+
let status = self.port_states[highlighted].try_get().unwrap_or(false);
194+
self.port_requests[highlighted].set(!status);
195+
}
186196
}
187197
}
188198
}

src/usb_hub.rs

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,8 @@ pub struct UsbDevice {
145145

146146
#[derive(Clone)]
147147
pub struct UsbPort {
148-
pub powered: Arc<Topic<bool>>,
148+
pub request: Arc<Topic<bool>>,
149+
pub status: Arc<Topic<bool>>,
149150
pub device: Arc<Topic<Option<UsbDevice>>>,
150151
}
151152

@@ -157,30 +158,34 @@ pub struct UsbHub {
157158

158159
fn handle_port(bb: &mut BrokerBuilder, name: &'static str, base: &'static str) -> UsbPort {
159160
let port = UsbPort {
160-
powered: bb.topic_rw(format!("/v1/usb/host/{name}/powered").as_str(), None),
161+
request: bb.topic_wo(format!("/v1/usb/host/{name}/powered").as_str(), None),
162+
status: bb.topic_ro(format!("/v1/usb/host/{name}/powered").as_str(), None),
161163
device: bb.topic_ro(format!("/v1/usb/host/{name}/device").as_str(), Some(None)),
162164
};
163165

164-
let powered = port.powered.clone();
166+
let request = port.request.clone();
167+
let status = port.status.clone();
165168
let device = port.device.clone();
166169
let disable_path = Path::new(base).join("disable");
167170

168171
// Spawn a task that turns USB port power on or off upon request.
169172
// Also clears the device info upon power off so it does not contain stale
170173
// information until the next poll.
171174
spawn(async move {
172-
let (mut src, _) = powered.subscribe_unbounded();
175+
let (mut src, _) = request.subscribe_unbounded();
173176

174177
while let Some(ev) = src.next().await {
175178
write(&disable_path, if ev { b"0" } else { b"1" }).unwrap();
176179

177180
if !ev {
178181
device.set(None);
179182
}
183+
184+
status.set(ev);
180185
}
181186
});
182187

183-
let powered = port.powered.clone();
188+
let status = port.status.clone();
184189
let device = port.device.clone();
185190
let disable_path = Path::new(base).join("disable");
186191
let (id_product_path, id_vendor_path, manufacturer_path, product_path) = {
@@ -204,7 +209,7 @@ fn handle_port(bb: &mut BrokerBuilder, name: &'static str, base: &'static str) -
204209
_ => panic!("Read unexpected value for USB port disable state"),
205210
};
206211

207-
powered.set_if_changed(is_powered);
212+
status.set_if_changed(is_powered);
208213
}
209214

210215
let id_product = read_to_string(&id_product_path).ok();

0 commit comments

Comments
 (0)