Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add udev_hwdb feature and fix cross build with feature enabled #16

Merged
merged 7 commits into from
Nov 22, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 7 additions & 7 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,10 @@ jobs:
fail-fast: false
matrix:
job:
# - { os: ubuntu-latest, target: aarch64-unknown-linux-gnu, use-cross: true }
- { os: ubuntu-latest, target: x86_64-pc-windows-gnu, use-cross: true }
- { os: ubuntu-latest, target: x86_64-unknown-linux-gnu, use-cross: false }
- { os: macos-latest, target: universal-apple-darwin, use-cross: false }
- { os: ubuntu-latest, target: aarch64-unknown-linux-gnu, use-cross: true, feature-flags: "--all-features" }
- { os: ubuntu-latest, target: x86_64-pc-windows-gnu, use-cross: true, feature-flags: "--all-features" }
- { os: ubuntu-latest, target: x86_64-unknown-linux-gnu, use-cross: false, feature-flags: "--all-features" }
- { os: macos-latest, target: universal-apple-darwin, use-cross: false, feature-flags: "--all-features" }
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@v1
Expand Down Expand Up @@ -90,14 +90,14 @@ jobs:
run: |
case ${{ matrix.job.target }} in
universal-apple-*)
cargo build --locked --release --all-features --target=aarch64-apple-darwin
cargo build --locked --release --all-features --target=x86_64-apple-darwin
cargo build --locked --release ${{ matrix.job.feature-flags }} --target=aarch64-apple-darwin
cargo build --locked --release ${{ matrix.job.feature-flags }} --target=x86_64-apple-darwin
mkdir -p target/universal-apple-darwin/release
# merge into universal
lipo -create -output target/universal-apple-darwin/release/cyme target/aarch64-apple-darwin/release/cyme target/x86_64-apple-darwin/release/cyme
;;
*)
${{ env.CARGO_CMD }} build --locked --release --all-features --target=${{ matrix.job.target }}
${{ env.CARGO_CMD }} build --locked --release ${{ matrix.job.feature-flags }} --target=${{ matrix.job.target }}
;;
esac

Expand Down
7 changes: 3 additions & 4 deletions Cargo.lock

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

22 changes: 15 additions & 7 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ clap = { version = "4.0.22", features = ["derive", "wrap_help"] }
colored = "2.0.0"
itertools = "0.10.5"
lazy_static = "1.4.0"
rusb = { git = "https://github.com/tuna-f1sh/rusb.git", version = "0.9.1", optional = true }
rusb = { version = "0.9.1", optional = true }
log = "0.4.17"
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0.87"
Expand All @@ -32,25 +32,30 @@ terminal_size = "0.2.5"
strum = "0.24.1"
strum_macros = "0.24.3"

[patch.crates-io]
libudev-sys = { git = "https://github.com/Emilgardis/libudev-sys/", branch = "fix-cross-compilation" }
rusb = { git = "https://github.com/a1ien/rusb.git" }

[dev-dependencies]
diff = "0.1"
assert-json-diff = "2.0.2"

[target.x86_64-unknown-linux-gnu.dependencies]
udev = { version = "^0.8.0", optional = true, features = ["hwdb"] }
rusb = { git = "https://github.com/tuna-f1sh/rusb.git", version = "0.9.1" }
udev = { version = "^0.8.0", optional = true }
rusb = "0.9.1"

[target.arm-unknown-linux-gnueabihf.dependencies]
udev = { version = "^0.8.0", optional = true, features = ["hwdb"] }
rusb = { git = "https://github.com/tuna-f1sh/rusb.git", version = "0.9.1" }
udev = { version = "^0.8.0", optional = true }
rusb = "0.9.1"

[target.aarch64-unknown-linux-gnu.dependencies]
udev = { version = "^0.8.0", optional = true, features = ["hwdb"] }
rusb = { git = "https://github.com/tuna-f1sh/rusb.git", version = "0.9.1" }
udev = { version = "^0.8.0", optional = true }
rusb = "0.9.1"

[features]
libusb = ["dep:rusb"]
udev = ["dep:udev"]
udev_hwdb = ["udev/hwdb"]
usb_test = []
cli_generate = ["dep:clap_complete", "dep:clap_mangen"] # for generating man and completions
default = ["libusb"]
Expand All @@ -65,6 +70,9 @@ strip = true
panic = "abort"
codegen-units = 1 # quicker binary, slower build

# [package.metadata.cross.build]
# pre-build = ["dpkg --add-architecture $CROSS_DEB_ARCH && apt-get update && apt-get install --assume-yes libusb-1.0-0-dev:$CROSS_DEB_ARCH libudev-dev:$CROSS_DEB_ARCH"]

[package.metadata.cross.target.arm-unknown-linux-gnueabihf]
pre-build = ["dpkg --add-architecture armhf && apt-get update && apt-get install --assume-yes libusb-1.0-0-dev:armhf libudev-dev:armhf"]

Expand Down
6 changes: 4 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ The name comes from the technical term for the type of blossom on a Apple tree:
## Requirements

* Linux/Windows and pre-compiled targets require [libusb 1.0.0](https://libusb.info): `brew install libusb`, `sudo apt install libusb-1.0-0-dev` or one's package manager of choice.
* Linux pre-compiled and `--features udev` requires 'libudev-dev': `sudo apt install libudev-dev` or one's package manager of choice.
* Linux pre-compiled and `--features udev`/`--features udev_hwdb` requires 'libudev-dev': `sudo apt install libudev-dev` or one's package manager of choice.

For pre-compiled binaries, see the [releases](https://github.com/tuna-f1sh/cyme/releases).

Expand All @@ -68,7 +68,9 @@ More package managers to come/package distribution, please feel free to create a

## Linux udev

To obtain device and interface drivers being used on Linux like `lsusb`, one must install 'libudev-dev' via a package manager and the `--features udev` feature when building. Only supported on Linux targets.
To obtain device and interface drivers being used on Linux like `lsusb`, one must install 'libudev-dev' via a package manager and the `--features udev` feature when building. To lookup USB IDs from the udev hwdb as well (like `lsusb`) use `--features udev_hwdb`. Without hwdb, `cyme` will use the 'usb-ids' crate, which is the same source as the hwdb binary data but the bundled hwdb may differ due to customisations or last update ('usb-ids' will be most up to date).

Only supported on Linux targets.

## Alias `lsusb`

Expand Down
3 changes: 1 addition & 2 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,7 @@ pub mod icon;
pub mod lsusb;
pub mod system_profiler;
pub mod types;
#[cfg(target_os = "linux")]
#[cfg(feature = "udev")]
#[cfg(all(target_os = "linux", feature = "udev"))]
pub mod udev;
pub mod usb;

Expand Down
10 changes: 6 additions & 4 deletions src/lsusb.rs
Original file line number Diff line number Diff line change
Expand Up @@ -830,15 +830,17 @@ pub mod names {
}

/// Wrapper around [`crate::udev::hwdb_get`] so that it can be 'used' without feature
///
/// Returns `Err` not `None` if feature is not enabled so that with unwrap_or hwdb can still return `None` if no match in db
#[allow(unused_variables)]
fn hwdb_get(modalias: &str, key: &'static str) -> Result<Option<String>, Error> {
#[cfg(all(target_os = "linux", feature = "udev"))]
return crate::udev::hwdb_get(modalias, key);
#[cfg(all(target_os = "linux", feature = "udev_hwdb"))]
return crate::udev::hwdb::get(modalias, key);

#[cfg(not(all(target_os = "linux", feature = "udev")))]
#[cfg(not(all(target_os = "linux", feature = "udev_hwdb")))]
return Err(Error::new(
ErrorKind::Unsupported,
"hwdb_get requires 'udev' feature",
"hwdb_get requires 'udev_hwdb' feature",
));
}
}
Expand Down
59 changes: 33 additions & 26 deletions src/udev.rs
Original file line number Diff line number Diff line change
Expand Up @@ -124,34 +124,41 @@ pub fn get_udev_attribute<T: AsRef<std::ffi::OsStr> + std::fmt::Display>(
.map(|s| s.to_str().unwrap_or("").to_string()))
}

/// Lookup an entry in the udev hwdb given the `modalias` and `key`.
/// udev hwdb lookup functions
///
/// Should act like https://github.com/gregkh/usbutils/blob/master/names.c#L115
///
/// ```
/// use cyme::udev::hwdb_get;
///
/// let modalias = "usb:v1D6Bp0001";
/// let vendor = hwdb_get(&modalias, "ID_VENDOR_FROM_DATABASE").unwrap();
///
/// assert_eq!(vendor, Some("Linux Foundation".into()));
///
/// let modalias = "usb:v*p*d*dc03dsc01dp01*";
/// let vendor = hwdb_get(&modalias, "ID_USB_PROTOCOL_FROM_DATABASE").unwrap();
///
/// assert_eq!(vendor, Some("Keyboard".into()));
/// ```
pub fn hwdb_get(modalias: &str, key: &'static str) -> Result<Option<String>, Error> {
let hwdb = udevlib::Hwdb::new().map_err(|e| {
Error::new(
ErrorKind::Udev,
&format!("Failed to get hwdb: Error({})", e),
)
})?;
/// Protected by the `udev_hwdb` feature because 'libudev-sys' excludes hwdb ffi bindings if native udev does not support hwdb
#[cfg(feature = "udev_hwdb")]
pub mod hwdb {
use super::*;
/// Lookup an entry in the udev hwdb given the `modalias` and `key`.
///
/// Should act like https://github.com/gregkh/usbutils/blob/master/names.c#L115
///
/// ```
/// use cyme::udev;
///
/// let modalias = "usb:v1D6Bp0001";
/// let vendor = hwdb::get(&modalias, "ID_VENDOR_FROM_DATABASE").unwrap();
///
/// assert_eq!(vendor, Some("Linux Foundation".into()));
///
/// let modalias = "usb:v*p*d*dc03dsc01dp01*";
/// let vendor = hwdb::get(&modalias, "ID_USB_PROTOCOL_FROM_DATABASE").unwrap();
///
/// assert_eq!(vendor, Some("Keyboard".into()));
/// ```
pub fn get(modalias: &str, key: &'static str) -> Result<Option<String>, Error> {
let hwdb = udevlib::Hwdb::new().map_err(|e| {
Error::new(
ErrorKind::Udev,
&format!("Failed to get hwdb: Error({})", e),
)
})?;

Ok(hwdb
.query_one(&modalias.to_string(), &key.to_string())
.map(|s| s.to_str().unwrap_or("").to_string()))
Ok(hwdb
.query_one(&modalias.to_string(), &key.to_string())
.map(|s| s.to_str().unwrap_or("").to_string()))
}
}

#[cfg(test)]
Expand Down