Skip to content

Commit

Permalink
demo+usb: Display the device description obtained from the acquired d…
Browse files Browse the repository at this point in the history
…evice

Added rusb to the crates.
Added libusb to the manifest.

Signed-off-by: Hubert Figuière <[email protected]>
  • Loading branch information
hfiguiere committed Nov 22, 2024
1 parent b15349c commit 3aee673
Show file tree
Hide file tree
Showing 5 changed files with 136 additions and 66 deletions.
29 changes: 29 additions & 0 deletions ashpd-demo/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions ashpd-demo/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ gettext-rs = {version = "0.7", features = ["gettext-system"]}
gst = {package = "gstreamer", version = "0.23"}
gst4gtk = {package = "gst-plugin-gtk4", version = "0.13", features = ["wayland", "x11egl", "x11glx", "gtk_v4_14"]}
gtk = {package = "gtk4", version = "0.9", features = ["v4_14"]}
rusb = "0.9.4"
serde = {version = "1.0", features = ["derive"]}
shumate = {version = "0.6", package = "libshumate"}
tracing = "0.1"
Expand Down
13 changes: 13 additions & 0 deletions ashpd-demo/build-aux/com.belmoussaoui.ashpd.demo.Devel.json
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,19 @@
]
},
"modules": [
{
"name": "libusb",
"config-opts": [
"--disable-udev"
],
"sources": [
{
"type": "archive",
"url": "https://github.com/libusb/libusb/releases/download/v1.0.23/libusb-1.0.23.tar.bz2",
"sha256": "db11c06e958a82dac52cf3c65cb4dd2c3f339c8a988665110e0d24d19312ad8d"
}
]
},
{
"name": "libshumate",
"buildsystem": "meson",
Expand Down
152 changes: 89 additions & 63 deletions ashpd-demo/src/portals/desktop/usb.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,9 @@
// Hubert Figuière <[email protected]>
//

use std::cell::RefCell;
use std::collections::HashMap;
use std::sync::Arc;
use std::{cell::RefCell, collections::HashMap, os::fd::AsRawFd, sync::Arc};

use adw::{prelude::*, subclass::prelude::*};
use futures_util::{lock::Mutex, StreamExt};
use glib::clone;
use gtk::glib;

use ashpd::zbus::zvariant::ObjectPath;
use ashpd::{
desktop::{
usb::{Device, UsbOptions, UsbProxy},
Expand Down Expand Up @@ -131,6 +124,22 @@ mod imp {
}
}

fn usb_describe_device(fd: &dyn AsRawFd) -> ashpd::Result<String> {
let context = rusb::Context::new()
.map_err(|_| ashpd::PortalError::Failed("rusb Context".to_string()))?;
let handle = unsafe { context.open_device_with_fd(fd.as_raw_fd()) }
.map_err(|_| ashpd::PortalError::Failed("open USB device".to_string()))?;
let device = handle.device();
let device_desc = device.device_descriptor().unwrap();
Ok(format!(
"Bus {:03} Device {:03} ID {:04x}:{:04x}",
device.bus_number(),
device.address(),
device_desc.vendor_id(),
device_desc.product_id()
))
}

pub(super) async fn refresh_devices(&self) -> ashpd::Result<()> {
let page = self.obj();

Expand All @@ -152,54 +161,16 @@ mod imp {
row.connect_share_clicked(clone!(
#[strong]
page,
move |row| {
move |widget| {
glib::spawn_future_local(clone!(
#[strong]
row,
#[strong]
device_id,
#[strong]
widget,
#[strong]
page,
async move {
let root = row.native().unwrap();
let identifier = WindowIdentifier::from_native(&root).await;
let usb = UsbProxy::new().await.unwrap();
let result = usb
.acquire_devices(&identifier, &[(&device_id, device_writable)])
.await;
match result {
Ok(resp) => {
if resp.response().is_ok() {
loop {
let result = usb.finish_acquire_devices().await;
match result {
Ok(result) => {
println!("result {result:?}");
if !result.1 {
continue;
}
for device in &result.0 {
page.imp().acquired_device(&device.0);
}
}
Err(err) => {
tracing::error!(
"Finish acquire device error: {err}"
);
page.error(&format!(
"Finish acquire device error: {err}"
));
}
}
break;
}
}
}
Err(err) => {
tracing::error!("Acquire device error: {err}");
page.error(&format!("Acquire device error: {err}"));
}
}
page.imp().share(&widget, &device_id, device_writable).await
}
));
}
Expand All @@ -214,19 +185,7 @@ mod imp {
device_id,
#[strong]
page,
async move {
let usb = UsbProxy::new().await.unwrap();
let result = usb.release_devices(&[&device_id]).await;
println!("{result:?}");
match result {
Ok(_) => {}
Err(err) => {
tracing::error!("Acquire device error: {err}");
page.error(&format!("Acquire device error: {err}"));
}
}
page.imp().released_device(&device_id);
}
async move { page.imp().unshare(&device_id).await }
));
}
));
Expand All @@ -235,6 +194,73 @@ mod imp {
Ok(())
}

async fn finish_acquire_device(&self, usb: &UsbProxy<'_>, object_path: &ObjectPath<'_>) {
loop {
let result = usb.finish_acquire_devices(object_path).await;
match result {
Ok(result) => {
println!("result {result:?}");
if !result.1 {
continue;
}
for device in &result.0 {
if let Ok(fd) = &device.1 {
match Self::usb_describe_device(&Fd::from(fd)) {
Ok(describe) => self.obj().info(&describe),
Err(err) => self.obj().info(&err.to_string()),
}
}
self.acquired_device(&device.0);
}
}
Err(err) => {
tracing::error!("Finish acquire device error: {err}");
self.obj()
.error(&format!("Finish acquire device error: {err}"));
}
}
break;
}
}

async fn share(&self, widget: &gtk::Button, device_id: &String, device_writable: bool) {
let root = widget.native().unwrap();
let identifier = WindowIdentifier::from_native(&root).await;
let usb = UsbProxy::new().await.unwrap();
let result = usb
.acquire_devices(
identifier.as_ref(),
&[Device(device_id.to_string(), device_writable)],
)
.await;
match result {
Ok(resp) => {
if resp.response().is_ok() {
let path = resp.path();
self.finish_acquire_device(&usb, path).await;
}
}
Err(err) => {
tracing::error!("Acquire device error: {err}");
self.obj().error(&format!("Acquire device error: {err}"));
}
}
}

async fn unshare(&self, device_id: &str) {
let usb = UsbProxy::new().await.unwrap();
let result = usb.release_devices(&[device_id]).await;
println!("{result:?}");
match result {
Ok(_) => {}
Err(err) => {
tracing::error!("Acquire device error: {err}");
self.obj().error(&format!("Acquire device error: {err}"));
}
}
self.released_device(device_id);
}

pub(super) async fn start_session(&self) -> ashpd::Result<()> {
let usb = UsbProxy::new().await?;
let session = usb.create_session().await?;
Expand Down
7 changes: 4 additions & 3 deletions src/desktop/usb.rs
Original file line number Diff line number Diff line change
Expand Up @@ -211,10 +211,11 @@ impl<'a> UsbProxy<'a> {
#[doc(alias = "AcquireDevices")]
pub async fn acquire_devices(
&self,
parent_window: &WindowIdentifier,
devices: &[(&String, bool)],
parent_window: Option<&WindowIdentifier>,
devices: &[Device],
) -> Result<Request<()>, Error> {
let options = AcquireOptions::default();
let parent_window = parent_window.map(|i| i.to_string()).unwrap_or_default();
let acquire_devices: Vec<(String, AcquireDevice)> = devices
.iter()
.map(|dev| {
Expand All @@ -226,7 +227,7 @@ impl<'a> UsbProxy<'a> {
.empty_request(
&options.handle_token,
"AcquireDevices",
&(parent_window, &acquire_devices, &options),
&(&parent_window, &acquire_devices, &options),
)
.await
}
Expand Down

0 comments on commit 3aee673

Please sign in to comment.