Skip to content

Commit

Permalink
README
Browse files Browse the repository at this point in the history
  • Loading branch information
tuna-f1sh committed Nov 14, 2022
1 parent 37e8fef commit ed8c17b
Show file tree
Hide file tree
Showing 5 changed files with 50 additions and 10 deletions.
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ license = "GPL-3.0-or-later"
version = "0.1.1"
edition = "2021"
categories = ["command-line-utilities"]
exclude = ["./img/*"]

[dependencies]
clap = { version = "4.0.22", features = ["derive"] }
Expand Down
31 changes: 31 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# Cyme

![cli tree output](./img/cli-tree.png)

A macOS `system_profiler SPUSBDataType` parser and utility that attempts to maintain compatibility with but also build upon `lsusb`. The project started as a quick replacement for the barely working [lsusb script](https://github.com/jlhonora/lsusb) and is my _yearly_ Rust project to keep up to date!

I'd like to build this into a modern `lsusb` tool, akin to `lsd`, `fd` etc. It is currently in flux as I build the foundations, learn about custom serde Deserializers and newer Rust features.

The name comes from the technical term for the type of blossom on a Apple tree: [cyme](https://en.wikipedia.org/wiki/Inflorescence#Determinate_or_cymose) - it is Apple related and also looks like a USB device tree 😃🌸.

## Planned Features

* Controllable block data like `lsd --blocks`
* Vendor ID nerd font icon look up and icon theming like `lsd --icon`.
* Interface and Device Descriptor icon look up.
* Modern drawing of device tree with utf-8 boxes.
* Tree support of all device interfaces and endpoints.

# Install

Clone this directory and with a Rust toolchain installed: `cargo install --path cyme`

## Alias `lsusb`

If you want to create a macOS version of lsusb, create an alias in your environment with the `--lsusb` compatibility flag:

`alias lsusb='cyme --lsusb'`

# Usage

Will cover this more as it develops. Use `cyme --help` for basic usage.
Binary file added img/cli-tree.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
8 changes: 6 additions & 2 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ struct Args {
lsusb_tree: bool,

/// Modern dump the physical USB device hierarchy as a tree
#[arg(short = 'T', long, default_value_t = true)]
#[arg(short = 'T', long, default_value_t = false)]
tree: bool,

/// Show only devices with the specified vendor and product ID numbers (in hexadecimal) in format VID:[PID]
Expand All @@ -33,6 +33,10 @@ struct Args {
#[arg(short, long)]
show: Option<String>,

/// Hide empty buses and hub; those with no devices
#[arg(long, default_value_t = false)]
hide_empty: bool,

/// Increase verbosity (show descriptors) TODO
// #[arg(short, long, default_value_t = false)]
// verbose: bool,
Expand Down Expand Up @@ -145,7 +149,7 @@ fn main() {
log::info!("{:?}", filter);

if args.vidpid.is_some() || args.show.is_some() {
let mut devs = sp_usb.get_all_devices();
let mut devs = sp_usb.flatten_devices();
devs = filter.filter_devices_ref(devs);
for d in devs {
if args.lsusb {
Expand Down
20 changes: 12 additions & 8 deletions src/system_profiler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -67,10 +67,11 @@ pub struct SPUSBDataType {
}

impl SPUSBDataType {
pub fn get_all_devices<'a>(&'a self) -> Vec<&'a USBDevice> {
/// Returns a flattened Vec of all the USBDevices returned from system_profiler as a reference
pub fn flatten_devices<'a>(&'a self) -> Vec<&'a USBDevice> {
let mut ret = Vec::new();
for bus in &self.buses {
ret.append(&mut bus.get_all_devices());
ret.append(&mut bus.flatten_devices());
}

ret
Expand Down Expand Up @@ -114,8 +115,9 @@ pub struct USBBus {
devices: Option<Vec<USBDevice>>,
}

/// Returns of Vec of devices in the USBBus as a reference
impl USBBus {
pub fn get_all_devices<'a>(&'a self) -> Vec<&'a USBDevice> {
pub fn flatten_devices<'a>(&'a self) -> Vec<&'a USBDevice> {
if let Some(devices) = &self.devices {
get_all_devices(&devices)
} else {
Expand All @@ -124,6 +126,7 @@ impl USBBus {
}
}

/// Recursively gets reference to all devices in a `USBDevice`
pub fn get_all_devices(devices: &Vec<USBDevice>) -> Vec<&USBDevice> {
let mut ret: Vec<&USBDevice> = Vec::new();
for device in devices {
Expand Down Expand Up @@ -183,23 +186,24 @@ impl fmt::Display for USBBus {
if f.alternate() {
writeln!(
f,
"{:}{:} {:} PCI Device: {:}:{:} Revision: {:04x}",
"{:}{:} {:} {:}:{:} Revision: 0x{:04x}",
tree.bright_black().bold(),
self.name.blue(),
self.host_controller.green(),
format!("{:04x}", self.pci_vendor.unwrap_or(0xffff))
format!("0x{:04x}", self.pci_vendor.unwrap_or(0xffff))
.yellow()
.bold(),
format!("{:04x}", self.pci_device.unwrap_or(0xffff)).yellow(),
format!("0x{:04x}", self.pci_device.unwrap_or(0xffff)).yellow(),
self.pci_revision.unwrap_or(0xffff),
)?;
// lsusb style but not really accurate...
} else {
writeln!(
f,
"{:}Bus {:03} Device 000 ID {:04x}:{:04x} {:} {:}",
"{:}Bus {:03} Device 000: ID {:04x}:{:04x} {:} {:}",
tree,
self.usb_bus_number.unwrap_or(0),
// bus number is not always provided in host json so try to extract from first device
self.usb_bus_number.unwrap_or(self.devices.as_ref().map_or(None, |d| d.first().map(|dd| dd.location_id.bus)).unwrap_or(0)),
self.pci_vendor.unwrap_or(0xffff),
self.pci_device.unwrap_or(0xffff),
self.name,
Expand Down

0 comments on commit ed8c17b

Please sign in to comment.