From d7b8a73088b753ece88072e3c621deffd674ac87 Mon Sep 17 00:00:00 2001 From: Isaiah Inuwa Date: Sat, 16 May 2026 21:57:00 -0500 Subject: [PATCH 1/2] wip: query all devices at once --- Cargo.lock | 1 + credentialsd-common/src/client.rs | 4 +- credentialsd-common/src/model.rs | 20 ++- credentialsd-common/src/server.rs | 14 +- credentialsd-ui/src/client.rs | 5 + credentialsd-ui/src/gui/view_model/gtk/mod.rs | 2 + credentialsd-ui/src/gui/view_model/mod.rs | 12 +- credentialsd/Cargo.toml | 1 + credentialsd/src/credential_service/mod.rs | 156 ++++++++++++------ credentialsd/src/dbus/flow_control.rs | 80 ++++++++- credentialsd/src/dbus/ui_control.rs | 2 + 11 files changed, 228 insertions(+), 69 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index a1c226f1..8310c65d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -754,6 +754,7 @@ dependencies = [ "async-trait", "base64", "credentialsd-common", + "futures", "futures-lite", "gio", "libc", diff --git a/credentialsd-common/src/client.rs b/credentialsd-common/src/client.rs index 6e6573c2..d5fe31b6 100644 --- a/credentialsd-common/src/client.rs +++ b/credentialsd-common/src/client.rs @@ -13,9 +13,7 @@ pub trait FlowController { &self, ) -> impl Future, ()>> + Send; - fn get_hybrid_credential(&mut self) -> impl Future> + Send; - fn get_usb_credential(&mut self) -> impl Future> + Send; - fn get_nfc_credential(&mut self) -> impl Future> + Send; + fn start_discovery(&mut self) -> impl Future> + Send; fn subscribe( &mut self, ) -> impl Future< diff --git a/credentialsd-common/src/model.rs b/credentialsd-common/src/model.rs index 1ac9e8c3..5fe30bda 100644 --- a/credentialsd-common/src/model.rs +++ b/credentialsd-common/src/model.rs @@ -270,6 +270,9 @@ pub enum NfcState { } pub enum UserInteractedEvent { + /// Start discovery + DiscoveryRequested, + /* /// Start Hybrid discovery HybridDiscoveryRequested, @@ -278,7 +281,7 @@ pub enum UserInteractedEvent { /// Start USB discovery UsbDiscoveryRequested, - + */ /// Send client PIN. Length of the PIN MUST not be greater than 63 bytes. /// File descriptor must be memory-mapped to be read. ClientPinEntered(OwnedFd), @@ -292,17 +295,16 @@ pub enum UserInteractedEvent { impl std::fmt::Debug for UserInteractedEvent { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { - Self::HybridDiscoveryRequested => write!(f, "StartHybridDiscovery"), - Self::NfcDiscoveryRequested => write!(f, "StartNfcDiscovery"), - Self::UsbDiscoveryRequested => write!(f, "StartUsbDiscovery"), + Self::DiscoveryRequested => write!(f, stringify!(DiscoveryRequested)), Self::ClientPinEntered(_) => f - .debug_tuple("EnterClientPin") + .debug_tuple(stringify!(ClientPinEntered)) .field(&"******".to_string()) .finish(), - Self::CredentialSelected(arg0) => { - f.debug_tuple("SelectCredential").field(arg0).finish() - } - Self::RequestCancelled => write!(f, "CancelRequest"), + Self::CredentialSelected(arg0) => f + .debug_tuple(stringify!(CredentialSelected)) + .field(arg0) + .finish(), + Self::RequestCancelled => write!(f, stringify!(RequestCancelled)), } } } diff --git a/credentialsd-common/src/server.rs b/credentialsd-common/src/server.rs index 6ab4fd81..ee9bb307 100644 --- a/credentialsd-common/src/server.rs +++ b/credentialsd-common/src/server.rs @@ -49,9 +49,12 @@ const BACKGROUND_EVENT_ERROR_CREDENTIAL_EXCLUDED: u32 = 0x80000006; const BACKGROUND_EVENT_ERROR_PIN_ATTEMPTS_EXHAUSTED: u32 = 0x80000007; const BACKGROUND_EVENT_ERROR_PIN_NOT_SET: u32 = 0x80000008; +/* const USER_INTERACTED_EVENT_HYBRID_DISCOVERY_REQUESTED: u32 = 0x01; const USER_INTERACTED_EVENT_NFC_DISCOVERY_REQUESTED: u32 = 0x02; const USER_INTERACTED_EVENT_USB_DISCOVERY_REQUESTED: u32 = 0x03; +*/ +const USER_INTERACTED_EVENT_DISCOVERY_REQUESTED: u32 = 0x01; const USER_INTERACTED_EVENT_CLIENT_PIN_ENTERED: u32 = 0x04; const USER_INTERACTED_EVENT_CREDENTIAL_SELECTED: u32 = 0x05; const USER_INTERACTED_EVENT_REQUEST_CANCELLED: u32 = 0x06; @@ -426,6 +429,10 @@ impl Type for UserInteractedEvent { impl From<&UserInteractedEvent> for Structure<'_> { fn from(value: &UserInteractedEvent) -> Self { match value { + UserInteractedEvent::DiscoveryRequested => { + tag_value_to_struct(USER_INTERACTED_EVENT_DISCOVERY_REQUESTED, None) + } + /* UserInteractedEvent::HybridDiscoveryRequested => { tag_value_to_struct(USER_INTERACTED_EVENT_HYBRID_DISCOVERY_REQUESTED, None) } @@ -435,6 +442,7 @@ impl From<&UserInteractedEvent> for Structure<'_> { UserInteractedEvent::UsbDiscoveryRequested => { tag_value_to_struct(USER_INTERACTED_EVENT_USB_DISCOVERY_REQUESTED, None) } + */ UserInteractedEvent::ClientPinEntered(pin_fd) => tag_value_to_struct( USER_INTERACTED_EVENT_CLIENT_PIN_ENTERED, Some(Value::Fd(pin_fd.into())), @@ -457,15 +465,17 @@ impl TryFrom<&Structure<'_>> for UserInteractedEvent { let (tag, value) = parse_tag_value_struct(value)?; match tag { - USER_INTERACTED_EVENT_HYBRID_DISCOVERY_REQUESTED => { - Ok(UserInteractedEvent::HybridDiscoveryRequested) + USER_INTERACTED_EVENT_DISCOVERY_REQUESTED => { + Ok(UserInteractedEvent::DiscoveryRequested) } + /* USER_INTERACTED_EVENT_NFC_DISCOVERY_REQUESTED => { Ok(UserInteractedEvent::NfcDiscoveryRequested) } USER_INTERACTED_EVENT_USB_DISCOVERY_REQUESTED => { Ok(UserInteractedEvent::UsbDiscoveryRequested) } + */ USER_INTERACTED_EVENT_CLIENT_PIN_ENTERED => { let fd = value.downcast_ref::()?; let owned_fd = fd.try_to_owned()?; diff --git a/credentialsd-ui/src/client.rs b/credentialsd-ui/src/client.rs index 2366184f..51aba1a2 100644 --- a/credentialsd-ui/src/client.rs +++ b/credentialsd-ui/src/client.rs @@ -24,6 +24,10 @@ pub struct FlowControlClient { } impl FlowControlClient { + pub async fn discover_authenticators(&self) -> Result<(), ()> { + self.send(UserInteractedEvent::DiscoveryRequested).await + } + /* pub async fn discover_hybrid_authenticators(&self) -> Result<(), ()> { self.send(UserInteractedEvent::HybridDiscoveryRequested) .await @@ -36,6 +40,7 @@ impl FlowControlClient { pub async fn discover_usb_authenticators(&mut self) -> Result<(), ()> { self.send(UserInteractedEvent::UsbDiscoveryRequested).await } + */ pub async fn enter_client_pin(&mut self, pin: String) -> Result<(), ()> { let fd = match write_secret(pin) { diff --git a/credentialsd-ui/src/gui/view_model/gtk/mod.rs b/credentialsd-ui/src/gui/view_model/gtk/mod.rs index cff1d34f..e85d9a9d 100644 --- a/credentialsd-ui/src/gui/view_model/gtk/mod.rs +++ b/credentialsd-ui/src/gui/view_model/gtk/mod.rs @@ -261,9 +261,11 @@ impl ViewModel { button.connect_clicked(move |button| { let id = button.widget_name().to_string(); let tx = tx.clone(); + /* glib::spawn_future_local(async move { tx.send(ViewEvent::DeviceSelected(id)).await.unwrap(); }); + */ }); button.into() }); diff --git a/credentialsd-ui/src/gui/view_model/mod.rs b/credentialsd-ui/src/gui/view_model/mod.rs index 9fb4d82c..64fdc209 100644 --- a/credentialsd-ui/src/gui/view_model/mod.rs +++ b/credentialsd-ui/src/gui/view_model/mod.rs @@ -127,6 +127,12 @@ impl ViewModel { .unwrap(); } + pub(crate) async fn start_discovery(&self) { + let cred_service = self.flow_controller.lock().await; + (*cred_service).discover_authenticators().await.unwrap(); + } + + /* pub(crate) async fn select_device(&mut self, id: &str) { let device = self.devices.iter().find(|d| d.id == id).unwrap(); tracing::debug!("Device selected: {:?}", device); @@ -176,6 +182,7 @@ impl ViewModel { .await .unwrap(); } + */ pub(crate) async fn start_event_loop(&mut self) { let view_events = self.rx_event.clone().map(Event::View); @@ -189,11 +196,14 @@ impl ViewModel { Event::View(ViewEvent::Initiated) => { self.update_title().await; self.update_devices(self.devices.clone()).await; + self.start_discovery().await; } + /* Event::View(ViewEvent::DeviceSelected(id)) => { self.select_device(&id).await; println!("Selected device {id}"); } + */ Event::View(ViewEvent::PinEntered(pin)) => { let mut cred_service = self.flow_controller.lock().await; if cred_service.enter_client_pin(pin).await.is_err() { @@ -366,7 +376,7 @@ impl ViewModel { #[derive(Serialize, Deserialize)] pub enum ViewEvent { Initiated, - DeviceSelected(String), + // DeviceSelected(String), CredentialSelected(String), PinEntered(String), UserCancelled, diff --git a/credentialsd/Cargo.toml b/credentialsd/Cargo.toml index 10e0115c..639eb265 100644 --- a/credentialsd/Cargo.toml +++ b/credentialsd/Cargo.toml @@ -10,6 +10,7 @@ async-stream = "0.3.6" async-trait = "0.1.89" base64 = "0.22.1" credentialsd-common = { path = "../credentialsd-common" } +futures = "0.3.32" futures-lite.workspace = true libc.workspace = true libwebauthn = { version = "0.3.0", features = ["libnfc","pcsc"] } diff --git a/credentialsd/src/credential_service/mod.rs b/credentialsd/src/credential_service/mod.rs index 7bc8fc0a..7809708d 100644 --- a/credentialsd/src/credential_service/mod.rs +++ b/credentialsd/src/credential_service/mod.rs @@ -10,7 +10,7 @@ use std::{ }; use async_trait::async_trait; -use futures_lite::{FutureExt, Stream, StreamExt}; +use futures_lite::{stream, FutureExt, Stream, StreamExt}; use libwebauthn::{ self, ops::webauthn::{GetAssertionResponse, MakeCredentialResponse}, @@ -18,7 +18,10 @@ use libwebauthn::{ use nfc::{NfcEvent, NfcHandler, NfcState, NfcStateInternal}; use tokio::sync::oneshot; -use credentialsd_common::model::{Device, Error as CredentialServiceError, RequestId, Transport}; +use credentialsd_common::{ + model::{Device, Error as CredentialServiceError, RequestId, Transport}, + server::BackgroundEvent, +}; use crate::{ credential_service::{hybrid::HybridEvent, usb::UsbEvent}, @@ -59,11 +62,9 @@ pub trait ManageDevice { ) -> Result; async fn cancel_request(&self, request_id: RequestId); async fn get_available_public_key_devices(&self) -> Result, ()>; - async fn get_hybrid_credential( + async fn start_discovery( &self, - ) -> Pin + Send + 'static>>; - async fn get_nfc_credential(&self) -> Pin + Send + 'static>>; - async fn get_usb_credential(&self) -> Pin + Send + 'static>>; + ) -> Pin + Send + 'static>>; } #[derive(Debug)] @@ -90,6 +91,54 @@ impl } } +impl + CredentialService +{ + async fn get_hybrid_credential( + &self, + ) -> Pin + Send + 'static>> { + let guard = self.ctx.lock().unwrap(); + if let Some(RequestContext { ref request, .. }) = *guard { + let stream = self.hybrid_handler.lock().unwrap().start(request); + let ctx = self.ctx.clone(); + Box::pin(HybridStateStream { inner: stream, ctx }) + } else { + tracing::error!( + "Attempted to start hybrid credential flow, but no request context was found." + ); + todo!("Handle error when context is not set up.") + } + } + + async fn get_usb_credential(&self) -> Pin + Send + 'static>> { + let guard = self.ctx.lock().unwrap(); + if let Some(RequestContext { ref request, .. }) = *guard { + let stream = self.usb_handler.lock().unwrap().start(request); + let ctx = self.ctx.clone(); + Box::pin(UsbStateStream { inner: stream, ctx }) + } else { + tracing::error!( + "Attempted to start usb credential flow, but no request context was found." + ); + todo!("Handle error when context is not set up.") + } + } + + async fn get_nfc_credential(&self) -> Pin + Send + 'static>> { + let guard = self.ctx.lock().unwrap(); + if let Some(RequestContext { ref request, .. }) = *guard { + let stream = self.nfc_handler.lock().unwrap().start(request); + let ctx = self.ctx.clone(); + Box::pin(NfcStateStream { inner: stream, ctx }) + } else { + tracing::error!( + "Attempted to start nfc credential flow, but no request context was found." + ); + todo!("Handle error when context is not set up.") + } + } +} + #[async_trait] impl ManageDevice for CredentialService @@ -158,48 +207,27 @@ impl Manage Ok(devices) } - async fn get_hybrid_credential( + async fn start_discovery( &self, - ) -> Pin + Send + 'static>> { - let guard = self.ctx.lock().unwrap(); - if let Some(RequestContext { ref request, .. }) = *guard { - let stream = self.hybrid_handler.lock().unwrap().start(request); - let ctx = self.ctx.clone(); - Box::pin(HybridStateStream { inner: stream, ctx }) - } else { - tracing::error!( - "Attempted to start hybrid credential flow, but no request context was found." - ); - todo!("Handle error when context is not set up.") - } - } - - async fn get_usb_credential(&self) -> Pin + Send + 'static>> { - let guard = self.ctx.lock().unwrap(); - if let Some(RequestContext { ref request, .. }) = *guard { - let stream = self.usb_handler.lock().unwrap().start(request); - let ctx = self.ctx.clone(); - Box::pin(UsbStateStream { inner: stream, ctx }) - } else { - tracing::error!( - "Attempted to start usb credential flow, but no request context was found." - ); - todo!("Handle error when context is not set up.") - } - } - - async fn get_nfc_credential(&self) -> Pin + Send + 'static>> { - let guard = self.ctx.lock().unwrap(); - if let Some(RequestContext { ref request, .. }) = *guard { - let stream = self.nfc_handler.lock().unwrap().start(request); - let ctx = self.ctx.clone(); - Box::pin(NfcStateStream { inner: stream, ctx }) - } else { - tracing::error!( - "Attempted to start nfc credential flow, but no request context was found." - ); - todo!("Handle error when context is not set up.") - } + ) -> Pin + Send + 'static>> { + let usb = self + .get_usb_credential() + .await + .map(DeviceStateUpdate::from) + .boxed(); + /* + let nfc = self + .get_nfc_credential() + .await + .map(DeviceStateUpdate::from) + .boxed(); + */ + let hybrid = self + .get_hybrid_credential() + .await + .map(DeviceStateUpdate::from) + .boxed(); + futures::stream::select_all([usb, /* nfc, */ hybrid]).boxed() } } @@ -309,6 +337,40 @@ where } } +pub enum DeviceStateUpdate { + Hybrid(HybridState), + Nfc(NfcState), + Usb(UsbState), +} + +impl From for BackgroundEvent { + fn from(value: DeviceStateUpdate) -> Self { + match value { + DeviceStateUpdate::Hybrid(state) => (&state).into(), + DeviceStateUpdate::Nfc(state) => (&state).into(), + DeviceStateUpdate::Usb(state) => (&state).into(), + } + } +} + +impl From for DeviceStateUpdate { + fn from(value: HybridState) -> Self { + Self::Hybrid(value) + } +} + +impl From for DeviceStateUpdate { + fn from(value: NfcState) -> Self { + Self::Nfc(value) + } +} + +impl From for DeviceStateUpdate { + fn from(value: UsbState) -> Self { + Self::Usb(value) + } +} + fn complete_request(ctx: &Mutex>, response: CredentialResponse) { if let Some(ctx) = ctx.lock().unwrap().take() { ctx.send_response(Ok(response)); diff --git a/credentialsd/src/dbus/flow_control.rs b/credentialsd/src/dbus/flow_control.rs index 8e8982b9..8f9f9774 100644 --- a/credentialsd/src/dbus/flow_control.rs +++ b/credentialsd/src/dbus/flow_control.rs @@ -23,7 +23,7 @@ use tokio::sync::{mpsc::Sender, Mutex as AsyncMutex}; use tokio::task::AbortHandle; use zbus::connection::Connection; -use crate::credential_service::ManageDevice; +use crate::credential_service::{nfc::NfcState, DeviceStateUpdate, ManageDevice}; use crate::dbus::ui_control::Ceremony; use crate::dbus::UiControlServiceClient; use crate::{ @@ -154,6 +154,7 @@ async fn handle { let stream = svc .lock() @@ -197,6 +198,41 @@ async fn handle { + let client_pin_tx = client_pin_tx.clone(); + let cred_selector_tx = cred_selector_tx.clone(); + let stream = + svc.lock() + .await + .start_discovery() + .await + .map(move |device_update| { + match &device_update { + DeviceStateUpdate::Nfc(NfcState::NeedsPin { + pin_tx, .. + }) => { + *client_pin_tx.lock().unwrap() = Some(pin_tx.clone()); + } + + DeviceStateUpdate::Usb(UsbState::NeedsPin { + pin_tx, .. + }) => { + *client_pin_tx.lock().unwrap() = Some(pin_tx.clone()); + } + DeviceStateUpdate::Usb(UsbState::SelectingCredential { + cred_tx, + .. + }) => { + *cred_selector_tx.lock().unwrap() = Some(cred_tx.clone()); + } + _ => {} + } + device_update.into() + }); + let flow = flow.clone(); + forward_background_event_stream(flow, stream); + } UserInteractedEvent::ClientPinEntered(pin_fd) => { let pin_fd = std::os::fd::OwnedFd::from(pin_fd); let pin = match read_secret(pin_fd.into()) { @@ -392,9 +428,12 @@ pub mod test { pub enum DummyFlowRequest { EnterClientPin(String), GetDevices, + GetCredential, + /* GetHybridCredential, GetUsbCredential, GetNfcCredential, + */ InitStream, } @@ -404,9 +443,11 @@ pub mod test { pub enum DummyFlowResponse { EnterClientPin(Result<(), ()>), GetDevices(Vec), - GetHybridCredential, - GetUsbCredential, - GetNfcCredential, + + GetCredential, + // GetHybridCredential, + // GetUsbCredential, + // GetNfcCredential, InitStream(Result + Send + 'static>>, ()>), } @@ -415,9 +456,10 @@ pub mod test { match self { Self::EnterClientPin(arg0) => f.debug_tuple("EnterClientPin").field(arg0).finish(), Self::GetDevices(arg0) => f.debug_tuple("GetDevices").field(arg0).finish(), - Self::GetHybridCredential => f.debug_tuple("GetHybridCredential").finish(), - Self::GetUsbCredential => f.debug_tuple("GetUsbCredential").finish(), - Self::GetNfcCredential => f.debug_tuple("GetNfcCredential").finish(), + Self::GetCredential => f.debug_tuple("GetCredential").finish(), + // Self::GetHybridCredential => f.debug_tuple("GetHybridCredential").finish(), + // Self::GetUsbCredential => f.debug_tuple("GetUsbCredential").finish(), + // Self::GetNfcCredential => f.debug_tuple("GetNfcCredential").finish(), Self::InitStream(_) => f .debug_tuple("InitStream") .field(&String::from("")) @@ -455,6 +497,17 @@ pub mod test { } } + async fn start_discovery(&mut self) -> Result<(), ()> { + if let Ok(DummyFlowResponse::GetCredential) = + self.send(DummyFlowRequest::GetCredential).await + { + Ok(()) + } else { + Err(()) + } + } + + /* async fn get_hybrid_credential(&mut self) -> Result<(), ()> { if let Ok(DummyFlowResponse::GetHybridCredential) = self.send(DummyFlowRequest::GetHybridCredential).await @@ -482,6 +535,7 @@ pub mod test { Err(()) } } + */ async fn subscribe( &mut self, @@ -576,6 +630,11 @@ pub mod test { let rsp = self.get_available_public_key_devices().await.unwrap(); DummyFlowResponse::GetDevices(rsp) } + DummyFlowRequest::GetCredential => { + self.start_discovery().await.unwrap(); + DummyFlowResponse::GetCredential + } + /* DummyFlowRequest::GetHybridCredential => { self.get_hybrid_credential().await.unwrap(); DummyFlowResponse::GetHybridCredential @@ -589,6 +648,7 @@ pub mod test { self.get_nfc_credential().await.unwrap(); DummyFlowResponse::GetNfcCredential } + */ DummyFlowRequest::InitStream => { let rsp = self.subscribe().await; DummyFlowResponse::InitStream(rsp) @@ -610,6 +670,11 @@ pub mod test { Ok(devices) } + async fn start_discovery(&mut self) -> Result<(), ()> { + unimplemented!(); + } + + /* async fn get_hybrid_credential(&mut self) -> Result<(), ()> { let svc = self.svc.lock().await; let mut stream = svc.get_hybrid_credential().await; @@ -715,6 +780,7 @@ pub mod test { } Ok(()) } + */ async fn subscribe( &mut self, diff --git a/credentialsd/src/dbus/ui_control.rs b/credentialsd/src/dbus/ui_control.rs index 7accb867..38f043e2 100644 --- a/credentialsd/src/dbus/ui_control.rs +++ b/credentialsd/src/dbus/ui_control.rs @@ -262,6 +262,7 @@ pub mod test { } } + /* pub async fn request_hybrid_credential(&self) { tracing::debug!( target: "DummyUiServer", @@ -327,6 +328,7 @@ pub mod test { .await .unwrap() } + */ pub async fn enter_client_pin(&self, pin: String) { tracing::debug!( From 280b1053a8521be84964414408df7e2e1c5a02ba Mon Sep 17 00:00:00 2001 From: Isaiah Inuwa Date: Sun, 17 May 2026 18:12:16 -0500 Subject: [PATCH 2/2] wip: ui: 0-click credential selection --- credentialsd-ui/data/resources/ui/window.ui | 42 +++++++++++++++++++++ credentialsd-ui/src/gui/view_model/mod.rs | 25 +++++++++++- credentialsd/src/credential_service/usb.rs | 8 +++- 3 files changed, 71 insertions(+), 4 deletions(-) diff --git a/credentialsd-ui/data/resources/ui/window.ui b/credentialsd-ui/data/resources/ui/window.ui index 2fe6d17c..07beb139 100644 --- a/credentialsd-ui/data/resources/ui/window.ui +++ b/credentialsd-ui/data/resources/ui/window.ui @@ -62,6 +62,46 @@ + + + start_page + Choose device + + + vertical + + + + + + CredentialsUiWindow + + + + + + + + Scan the QR code above with another device, or tap or activate your security key + + + + + + + + CredentialsUiWindow + + + + + + + + + + + choose_device @@ -151,6 +191,7 @@ + diff --git a/credentialsd-ui/src/gui/view_model/mod.rs b/credentialsd-ui/src/gui/view_model/mod.rs index 64fdc209..da9e4aff 100644 --- a/credentialsd-ui/src/gui/view_model/mod.rs +++ b/credentialsd-ui/src/gui/view_model/mod.rs @@ -238,7 +238,14 @@ impl ViewModel { } Event::Background(BackgroundEvent::UsbConnected) => { - info!("Found USB device") + info!("Found USB device"); + self.tx_update + .send(ViewUpdate::WaitingForDevice(Device { + id: "TODO: bogus".to_string(), + transport: Transport::Usb, + })) + .await + .unwrap(); } // TODO: Add this event // Event::Background(BackgroundEvent::DevicesUpdated(devices)) => { @@ -332,7 +339,14 @@ impl ViewModel { .unwrap() } Event::Background(BackgroundEvent::NfcConnected) => { - info!("Found NFC device") + info!("Found NFC device"); + self.tx_update + .send(ViewUpdate::WaitingForDevice(Device { + id: "TODO: bogus".to_string(), + transport: Transport::Nfc, + })) + .await + .unwrap(); } Event::Background(BackgroundEvent::NfcIdle | BackgroundEvent::NfcWaiting) => {} @@ -348,6 +362,13 @@ impl ViewModel { } Event::Background(BackgroundEvent::HybridConnecting) => { self.hybrid_qr_code_data = None; + self.tx_update + .send(ViewUpdate::WaitingForDevice(Device { + id: "TODO: bogus".to_string(), + transport: Transport::HybridQr, + })) + .await + .unwrap(); self.tx_update .send(ViewUpdate::HybridConnecting) .await diff --git a/credentialsd/src/credential_service/usb.rs b/credentialsd/src/credential_service/usb.rs index 35771b86..39aeebfd 100644 --- a/credentialsd/src/credential_service/usb.rs +++ b/credentialsd/src/credential_service/usb.rs @@ -46,9 +46,13 @@ impl InProcessUsbHandler { if hid_devices.is_empty() { let state = UsbStateInternal::Waiting; Ok(state) - } else if hid_devices.len() == 1 { + } + /* + else if hid_devices.len() == 1 { Ok(UsbStateInternal::Connected(hid_devices.swap_remove(0))) - } else { + } + */ + else { Ok(UsbStateInternal::SelectingDevice(hid_devices)) } }