diff --git a/doc/_cyme b/doc/_cyme index 27199f9e..98adec57 100644 --- a/doc/_cyme +++ b/doc/_cyme @@ -83,6 +83,7 @@ port-path\:"syspath style port path to bus, applicable to Linux only"))' \ number\:"Number of config, bConfigurationValue; value to set to enable to configuration" num-interfaces\:"Interfaces available for this configuruation" attributes\:"Attributes of configuration, bmAttributes" +icon-attributes\:"Icon representation of bmAttributes" max-power\:"Maximum current consumption in mA"))' \ '*--interface-blocks=[Specify the blocks which will be displayed for each interface and in what order]:INTERFACE_BLOCKS:((name\:"Name from string descriptor" number\:"Interface number" @@ -107,21 +108,26 @@ device-number\:"Sort by bus device number" no-sort\:"No sorting; whatever order it was parsed"))' \ '--group-devices=[Group devices by value when listing]:GROUP_DEVICES:((no-group\:"No grouping" bus\:"Group into buses with bus info as heading - like a flat tree"))' \ +'--from-json=[Read from json output rather than profiling system - must use --tree json dump]:FROM_JSON: ' \ '-l[Attempt to maintain compatibility with lsusb output]' \ '--lsusb[Attempt to maintain compatibility with lsusb output]' \ '-t[Dump USB device hierarchy as a tree]' \ '--tree[Dump USB device hierarchy as a tree]' \ '*-v[Verbosity level: 1 prints device configurations; 2 prints interfaces; 3 prints interface endpoints; 4 prints everything and all blocks]' \ '*--verbose[Verbosity level: 1 prints device configurations; 2 prints interfaces; 3 prints interface endpoints; 4 prints everything and all blocks]' \ +'-m[Print more blocks by default at each verbosity]' \ +'--more[Print more blocks by default at each verbosity]' \ '--sort-buses[Sort devices by bus number]' \ '--hide-buses[Hide empty buses; those with no devices]' \ '--hide-hubs[Hide empty hubs; those with no devices]' \ '--decimal[Show base16 values as base10 decimal instead]' \ '--no-padding[Disable padding to align blocks]' \ '--no-colour[Disable coloured output, can also use NO_COLOR environment variable]' \ +'--ascii[Disables icons and utf-8 charactors]' \ '--headings[Show block headings]' \ -'--json[Output as json format after sorting, filters and tree settings are applied]' \ -'--force-libusb[Force libusb mode on macOS rather than using system_profiler output]' \ +'--json[Output as json format after sorting, filters and tree settings are applied; without -tree will be flattened dump of devices]' \ +'-F[Force libusb profiler on macOS rather than using/combining system_profiler output]' \ +'--force-libusb[Force libusb profiler on macOS rather than using/combining system_profiler output]' \ '*-c[Turn debugging information on. Alternatively can use RUST_LOG env: INFO, DEBUG, TRACE]' \ '*--debug[Turn debugging information on. Alternatively can use RUST_LOG env: INFO, DEBUG, TRACE]' \ '--gen[Generate cli completions and man page]' \ diff --git a/doc/_cyme.ps1 b/doc/_cyme.ps1 index 5dbbfecb..c3606c6a 100644 --- a/doc/_cyme.ps1 +++ b/doc/_cyme.ps1 @@ -37,21 +37,26 @@ Register-ArgumentCompleter -Native -CommandName 'cyme' -ScriptBlock { [CompletionResult]::new('--endpoint-blocks', 'endpoint-blocks', [CompletionResultType]::ParameterName, 'Specify the blocks which will be displayed for each endpoint and in what order') [CompletionResult]::new('--sort-devices', 'sort-devices', [CompletionResultType]::ParameterName, 'Sort devices by value') [CompletionResult]::new('--group-devices', 'group-devices', [CompletionResultType]::ParameterName, 'Group devices by value when listing') + [CompletionResult]::new('--from-json', 'from-json', [CompletionResultType]::ParameterName, 'Read from json output rather than profiling system - must use --tree json dump') [CompletionResult]::new('-l', 'l', [CompletionResultType]::ParameterName, 'Attempt to maintain compatibility with lsusb output') [CompletionResult]::new('--lsusb', 'lsusb', [CompletionResultType]::ParameterName, 'Attempt to maintain compatibility with lsusb output') [CompletionResult]::new('-t', 't', [CompletionResultType]::ParameterName, 'Dump USB device hierarchy as a tree') [CompletionResult]::new('--tree', 'tree', [CompletionResultType]::ParameterName, 'Dump USB device hierarchy as a tree') [CompletionResult]::new('-v', 'v', [CompletionResultType]::ParameterName, 'Verbosity level: 1 prints device configurations; 2 prints interfaces; 3 prints interface endpoints; 4 prints everything and all blocks') [CompletionResult]::new('--verbose', 'verbose', [CompletionResultType]::ParameterName, 'Verbosity level: 1 prints device configurations; 2 prints interfaces; 3 prints interface endpoints; 4 prints everything and all blocks') + [CompletionResult]::new('-m', 'm', [CompletionResultType]::ParameterName, 'Print more blocks by default at each verbosity') + [CompletionResult]::new('--more', 'more', [CompletionResultType]::ParameterName, 'Print more blocks by default at each verbosity') [CompletionResult]::new('--sort-buses', 'sort-buses', [CompletionResultType]::ParameterName, 'Sort devices by bus number') [CompletionResult]::new('--hide-buses', 'hide-buses', [CompletionResultType]::ParameterName, 'Hide empty buses; those with no devices') [CompletionResult]::new('--hide-hubs', 'hide-hubs', [CompletionResultType]::ParameterName, 'Hide empty hubs; those with no devices') [CompletionResult]::new('--decimal', 'decimal', [CompletionResultType]::ParameterName, 'Show base16 values as base10 decimal instead') [CompletionResult]::new('--no-padding', 'no-padding', [CompletionResultType]::ParameterName, 'Disable padding to align blocks') [CompletionResult]::new('--no-colour', 'no-colour', [CompletionResultType]::ParameterName, 'Disable coloured output, can also use NO_COLOR environment variable') + [CompletionResult]::new('--ascii', 'ascii', [CompletionResultType]::ParameterName, 'Disables icons and utf-8 charactors') [CompletionResult]::new('--headings', 'headings', [CompletionResultType]::ParameterName, 'Show block headings') - [CompletionResult]::new('--json', 'json', [CompletionResultType]::ParameterName, 'Output as json format after sorting, filters and tree settings are applied') - [CompletionResult]::new('--force-libusb', 'force-libusb', [CompletionResultType]::ParameterName, 'Force libusb mode on macOS rather than using system_profiler output') + [CompletionResult]::new('--json', 'json', [CompletionResultType]::ParameterName, 'Output as json format after sorting, filters and tree settings are applied; without -tree will be flattened dump of devices') + [CompletionResult]::new('-F', 'F', [CompletionResultType]::ParameterName, 'Force libusb profiler on macOS rather than using/combining system_profiler output') + [CompletionResult]::new('--force-libusb', 'force-libusb', [CompletionResultType]::ParameterName, 'Force libusb profiler on macOS rather than using/combining system_profiler output') [CompletionResult]::new('-c', 'c', [CompletionResultType]::ParameterName, 'Turn debugging information on. Alternatively can use RUST_LOG env: INFO, DEBUG, TRACE') [CompletionResult]::new('--debug', 'debug', [CompletionResultType]::ParameterName, 'Turn debugging information on. Alternatively can use RUST_LOG env: INFO, DEBUG, TRACE') [CompletionResult]::new('--gen', 'gen', [CompletionResultType]::ParameterName, 'Generate cli completions and man page') diff --git a/doc/cyme.1 b/doc/cyme.1 index 568358d4..ab26b95f 100644 --- a/doc/cyme.1 +++ b/doc/cyme.1 @@ -1,12 +1,12 @@ .ie \n(.g .ds Aq \(aq .el .ds Aq ' -.TH cyme 1 "cyme 0.7.8" +.TH cyme 1 "cyme 0.8.5" .SH NAME -cyme \- List system USB buses and devices; a modern `lsusb` that attempts to maintain compatibility with, but also add new features +cyme \- List system USB buses and devices; a modern and compatiable `lsusb` .SH SYNOPSIS -\fBcyme\fR [\fB\-l\fR|\fB\-\-lsusb\fR] [\fB\-t\fR|\fB\-\-tree\fR] [\fB\-d\fR|\fB\-\-vidpid\fR] [\fB\-s\fR|\fB\-\-show\fR] [\fB\-D\fR|\fB\-\-device\fR] [\fB\-\-filter\-name\fR] [\fB\-\-filter\-serial\fR] [\fB\-v\fR|\fB\-\-verbose\fR]... [\fB\-b\fR|\fB\-\-blocks\fR] [\fB\-\-bus\-blocks\fR] [\fB\-\-config\-blocks\fR] [\fB\-\-interface\-blocks\fR] [\fB\-\-endpoint\-blocks\fR] [\fB\-\-sort\-devices\fR] [\fB\-\-sort\-buses\fR] [\fB\-\-group\-devices\fR] [\fB\-\-hide\-buses\fR] [\fB\-\-hide\-hubs\fR] [\fB\-\-decimal\fR] [\fB\-\-no\-padding\fR] [\fB\-\-no\-colour\fR] [\fB\-\-headings\fR] [\fB\-\-json\fR] [\fB\-\-force\-libusb\fR] [\fB\-c\fR|\fB\-\-debug\fR]... [\fB\-h\fR|\fB\-\-help\fR] [\fB\-V\fR|\fB\-\-version\fR] +\fBcyme\fR [\fB\-l\fR|\fB\-\-lsusb\fR] [\fB\-t\fR|\fB\-\-tree\fR] [\fB\-d\fR|\fB\-\-vidpid\fR] [\fB\-s\fR|\fB\-\-show\fR] [\fB\-D\fR|\fB\-\-device\fR] [\fB\-\-filter\-name\fR] [\fB\-\-filter\-serial\fR] [\fB\-v\fR|\fB\-\-verbose\fR]... [\fB\-b\fR|\fB\-\-blocks\fR] [\fB\-\-bus\-blocks\fR] [\fB\-\-config\-blocks\fR] [\fB\-\-interface\-blocks\fR] [\fB\-\-endpoint\-blocks\fR] [\fB\-m\fR|\fB\-\-more\fR] [\fB\-\-sort\-devices\fR] [\fB\-\-sort\-buses\fR] [\fB\-\-group\-devices\fR] [\fB\-\-hide\-buses\fR] [\fB\-\-hide\-hubs\fR] [\fB\-\-decimal\fR] [\fB\-\-no\-padding\fR] [\fB\-\-no\-colour\fR] [\fB\-\-ascii\fR] [\fB\-\-headings\fR] [\fB\-\-json\fR] [\fB\-\-from\-json\fR] [\fB\-F\fR|\fB\-\-force\-libusb\fR] [\fB\-c\fR|\fB\-\-debug\fR]... [\fB\-h\fR|\fB\-\-help\fR] [\fB\-V\fR|\fB\-\-version\fR] .SH DESCRIPTION -List system USB buses and devices; a modern `lsusb` that attempts to maintain compatibility with, but also add new features +List system USB buses and devices; a modern and compatiable `lsusb` .SH OPTIONS .TP \fB\-l\fR, \fB\-\-lsusb\fR=\fILSUSB\fR @@ -131,6 +131,8 @@ num\-interfaces: Interfaces available for this configuruation .IP \(bu 2 attributes: Attributes of configuration, bmAttributes .IP \(bu 2 +icon\-attributes: Icon representation of bmAttributes +.IP \(bu 2 max\-power: Maximum current consumption in mA .RE .TP @@ -188,6 +190,9 @@ max\-packet\-size: Maximum packet size in bytes endpoint can send/recieve interval: Interval for polling endpoint data transfers. Value in frame counts. Ignored for Bulk & Control Endpoints. Isochronous must equal 1 and field may range from 1 to 255 for interrupt endpoints .RE .TP +\fB\-m\fR, \fB\-\-more\fR=\fIMORE\fR +Print more blocks by default at each verbosity +.TP \fB\-\-sort\-devices\fR=\fISORT_DEVICES\fR Sort devices by value .br @@ -234,14 +239,20 @@ Disable padding to align blocks \fB\-\-no\-colour\fR=\fINO_COLOUR\fR Disable coloured output, can also use NO_COLOR environment variable .TP +\fB\-\-ascii\fR=\fIASCII\fR +Disables icons and utf\-8 charactors +.TP \fB\-\-headings\fR=\fIHEADINGS\fR Show block headings .TP \fB\-\-json\fR=\fIJSON\fR -Output as json format after sorting, filters and tree settings are applied +Output as json format after sorting, filters and tree settings are applied; without \-tree will be flattened dump of devices +.TP +\fB\-\-from\-json\fR=\fIFROM_JSON\fR +Read from json output rather than profiling system \- must use \-\-tree json dump .TP -\fB\-\-force\-libusb\fR=\fIFORCE_LIBUSB\fR -Force libusb mode on macOS rather than using system_profiler output +\fB\-F\fR, \fB\-\-force\-libusb\fR=\fIFORCE_LIBUSB\fR +Force libusb profiler on macOS rather than using/combining system_profiler output .TP \fB\-c\fR, \fB\-\-debug\fR=\fIDEBUG\fR Turn debugging information on. Alternatively can use RUST_LOG env: INFO, DEBUG, TRACE @@ -252,6 +263,6 @@ Print help information (use `\-h` for a summary) \fB\-V\fR, \fB\-\-version\fR Print version information .SH VERSION -v0.7.8 +v0.8.5 .SH AUTHORS John Whittington diff --git a/doc/cyme.bash b/doc/cyme.bash index 5c6cec55..605d2864 100644 --- a/doc/cyme.bash +++ b/doc/cyme.bash @@ -19,7 +19,7 @@ _cyme() { case "${cmd}" in cyme) - opts="-l -t -d -s -D -v -b -c -h -V --lsusb --tree --vidpid --show --device --filter-name --filter-serial --verbose --blocks --bus-blocks --config-blocks --interface-blocks --endpoint-blocks --sort-devices --sort-buses --group-devices --hide-buses --hide-hubs --decimal --no-padding --no-colour --headings --json --force-libusb --debug --gen --help --version" + opts="-l -t -d -s -D -v -b -m -F -c -h -V --lsusb --tree --vidpid --show --device --filter-name --filter-serial --verbose --blocks --bus-blocks --config-blocks --interface-blocks --endpoint-blocks --more --sort-devices --sort-buses --group-devices --hide-buses --hide-hubs --decimal --no-padding --no-colour --ascii --headings --json --from-json --force-libusb --debug --gen --help --version" if [[ ${cur} == -* || ${COMP_CWORD} -eq 1 ]] ; then COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) return 0 @@ -70,7 +70,7 @@ _cyme() { return 0 ;; --config-blocks) - COMPREPLY=($(compgen -W "name number num-interfaces attributes max-power" -- "${cur}")) + COMPREPLY=($(compgen -W "name number num-interfaces attributes icon-attributes max-power" -- "${cur}")) return 0 ;; --interface-blocks) @@ -89,6 +89,10 @@ _cyme() { COMPREPLY=($(compgen -W "no-group bus" -- "${cur}")) return 0 ;; + --from-json) + COMPREPLY=($(compgen -f "${cur}")) + return 0 + ;; *) COMPREPLY=() ;; diff --git a/doc/cyme.fish b/doc/cyme.fish index 2aa19697..a901d308 100644 --- a/doc/cyme.fish +++ b/doc/cyme.fish @@ -5,23 +5,26 @@ complete -c cyme -l filter-name -d 'Filter on string contained in name' -r complete -c cyme -l filter-serial -d 'Filter on string contained in serial' -r complete -c cyme -s b -l blocks -d 'Specify the blocks which will be displayed for each device and in what order' -r -f -a "{bus-number Number of bus device is attached,device-number Bus issued device number,branch-position Position of device in parent branch,port-path Linux style port path,sys-path Linux udev reported syspath,driver Linux udev reported driver loaded for device,icon Icon based on VID/PID,vendor-id Unique vendor identifier - purchased from USB IF,product-id Vendor unique product identifier,name The device name as reported in descriptor or using usb_ids if None,manufacturer The device manufacturer as provided in descriptor or using usb_ids if None,product-name The device product name as reported by usb_ids vidpid lookup,vendor-name The device vendor name as reported by usb_ids vid lookup,serial Device serial string as reported by descriptor,speed Advertised device capable speed,tree-positions Position along all branches back to trunk device,bus-power macOS system_profiler only - actually bus current in mA not power!,bus-power-used macOS system_profiler only - actually bus current used in mA not power!,extra-current-used macOS system_profiler only - actually bus current used in mA not power!,bcd-device The device version,bcd-usb The supported USB version,class-code Class of interface provided by USB IF - only available when using libusb,sub-class Sub-class of interface provided by USB IF - only available when using libusb,protocol Prototol code for interface provided by USB IF - only available when using libusb}" complete -c cyme -l bus-blocks -d 'Specify the blocks which will be displayed for each bus and in what order' -r -f -a "{bus-number System bus number identifier,icon Icon based on VID/PID,name Bus name from descriptor or usb_ids,host-controller Host Controller on macOS\, vendor put here when using libusb,pci-vendor Understood to be vendor ID - it is when using libusb,pci-device Understood to be product ID - it is when using libusb,pci-revision Revsision of hardware,port-path syspath style port path to bus\, applicable to Linux only}" -complete -c cyme -l config-blocks -d 'Specify the blocks which will be displayed for each configuration and in what order' -r -f -a "{name Name from string descriptor,number Number of config\, bConfigurationValue; value to set to enable to configuration,num-interfaces Interfaces available for this configuruation,attributes Attributes of configuration\, bmAttributes,max-power Maximum current consumption in mA}" +complete -c cyme -l config-blocks -d 'Specify the blocks which will be displayed for each configuration and in what order' -r -f -a "{name Name from string descriptor,number Number of config\, bConfigurationValue; value to set to enable to configuration,num-interfaces Interfaces available for this configuruation,attributes Attributes of configuration\, bmAttributes,icon-attributes Icon representation of bmAttributes,max-power Maximum current consumption in mA}" complete -c cyme -l interface-blocks -d 'Specify the blocks which will be displayed for each interface and in what order' -r -f -a "{name Name from string descriptor,number Interface number,port-path Interface port path\, applicable to Linux,class-code Class of interface provided by USB IF,sub-class Sub-class of interface provided by USB IF,protocol Prototol code for interface provided by USB IF,alt-setting Interfaces can have the same number but an alternate settings defined here,driver Driver obtained from udev on Linux only,sys-path syspath obtained from udev on Linux only,num-endpoints An interface can have many endpoints,icon Icon based on ClassCode/SubCode/Protocol}" complete -c cyme -l endpoint-blocks -d 'Specify the blocks which will be displayed for each endpoint and in what order' -r -f -a "{number Endpoint number on interface,direction Direction of data into endpoint,transfer-type Type of data transfer endpoint accepts,sync-type Synchronisation type (Iso mode),usage-type Usage type (Iso mode),max-packet-size Maximum packet size in bytes endpoint can send/recieve,interval Interval for polling endpoint data transfers. Value in frame counts. Ignored for Bulk & Control Endpoints. Isochronous must equal 1 and field may range from 1 to 255 for interrupt endpoints}" complete -c cyme -l sort-devices -d 'Sort devices by value' -r -f -a "{branch-position Sort by position in parent branch,device-number Sort by bus device number,no-sort No sorting; whatever order it was parsed}" complete -c cyme -l group-devices -d 'Group devices by value when listing' -r -f -a "{no-group No grouping,bus Group into buses with bus info as heading - like a flat tree}" +complete -c cyme -l from-json -d 'Read from json output rather than profiling system - must use --tree json dump' -r complete -c cyme -s l -l lsusb -d 'Attempt to maintain compatibility with lsusb output' complete -c cyme -s t -l tree -d 'Dump USB device hierarchy as a tree' complete -c cyme -s v -l verbose -d 'Verbosity level: 1 prints device configurations; 2 prints interfaces; 3 prints interface endpoints; 4 prints everything and all blocks' +complete -c cyme -s m -l more -d 'Print more blocks by default at each verbosity' complete -c cyme -l sort-buses -d 'Sort devices by bus number' complete -c cyme -l hide-buses -d 'Hide empty buses; those with no devices' complete -c cyme -l hide-hubs -d 'Hide empty hubs; those with no devices' complete -c cyme -l decimal -d 'Show base16 values as base10 decimal instead' complete -c cyme -l no-padding -d 'Disable padding to align blocks' complete -c cyme -l no-colour -d 'Disable coloured output, can also use NO_COLOR environment variable' +complete -c cyme -l ascii -d 'Disables icons and utf-8 charactors' complete -c cyme -l headings -d 'Show block headings' -complete -c cyme -l json -d 'Output as json format after sorting, filters and tree settings are applied' -complete -c cyme -l force-libusb -d 'Force libusb mode on macOS rather than using system_profiler output' +complete -c cyme -l json -d 'Output as json format after sorting, filters and tree settings are applied; without -tree will be flattened dump of devices' +complete -c cyme -s F -l force-libusb -d 'Force libusb profiler on macOS rather than using/combining system_profiler output' complete -c cyme -s c -l debug -d 'Turn debugging information on. Alternatively can use RUST_LOG env: INFO, DEBUG, TRACE' complete -c cyme -l gen -d 'Generate cli completions and man page' complete -c cyme -s h -l help -d 'Print help information (use `--help` for more detail)' diff --git a/doc/cyme_example.json b/doc/cyme_example.json new file mode 100644 index 00000000..5643955d --- /dev/null +++ b/doc/cyme_example.json @@ -0,0 +1,10 @@ +{ + "classifier#02": "", + "vid-pid-msb#0483:37": "", + "vid#2e8a": "", + "undefined-classifier": "☶", + "unknown-vendor": "", + "vid#05ac": "", + "vid-pid#1d50:6018": "", + "classifier-sub-protocol#15:01:01": "" +} \ No newline at end of file diff --git a/src/icon.rs b/src/icon.rs index 540e5e3e..311555b5 100644 --- a/src/icon.rs +++ b/src/icon.rs @@ -10,7 +10,6 @@ use crate::system_profiler::{USBBus, USBDevice}; use crate::usb::{ClassCode, Direction}; /// Icon type enum is used as key in `HashMaps` -/// TODO FromStr and ToStr serialize/deserialize so that can merge with user defined #[derive(Debug, Clone, Hash, PartialEq, Eq, SerializeDisplay, DeserializeFromStr)] pub enum Icon { /// Vendor ID lookup @@ -72,10 +71,11 @@ impl FromStr for Icon { } // enum contains value } else { - let (parse_ints, errors): (Vec<_>, Vec<_>) = value_split[1..].into_iter() - .map(|vs| vs.parse::()) + let (parse_ints, errors): (Vec>, Vec<_>) = value_split[1].split(":") + .map(|vs| u32::from_str_radix(vs.trim_start_matches("0x"), 16)) .partition(Result::is_ok); - let numbers: Vec<_> = parse_ints.into_iter().map(Result::unwrap).collect(); + let numbers: Vec = parse_ints.into_iter().map(|v| v.unwrap() as u16).collect(); + println!("{:?} {:?}", numbers, errors); if !errors.is_empty() { return Err(io::Error::new(io::ErrorKind::Other, "Invalid value in enum string after #")); @@ -86,11 +86,11 @@ impl FromStr for Icon { Some(i) => Ok(Icon::Vid(*i)), None => Err(io::Error::new(io::ErrorKind::Other, "No value for enum after $")) }, - "vid-pid" => match numbers.get(0..1) { + "vid-pid" => match numbers.get(0..2) { Some(slice) => Ok(Icon::VidPid((slice[0], slice[1]))), None => Err(io::Error::new(io::ErrorKind::Other, "No value for enum after $")) }, - "vid-pid-msb" => match numbers.get(0..1) { + "vid-pid-msb" => match numbers.get(0..2) { Some(slice) => Ok(Icon::VidPidMsb((slice[0], slice[1] as u8))), None => Err(io::Error::new(io::ErrorKind::Other, "No value for enum after $")) }, @@ -98,7 +98,7 @@ impl FromStr for Icon { Some(i) => Ok(Icon::Classifier(ClassCode::from(*i as u8))), None => Err(io::Error::new(io::ErrorKind::Other, "No value for enum after $")) }, - "classifier-sub-protocol" => match numbers.get(0..2) { + "classifier-sub-protocol" => match numbers.get(0..3) { Some(slice) => Ok(Icon::ClassifierSubProtocol((ClassCode::from(slice[0] as u8), slice[1] as u8, slice[2] as u8))), None => Err(io::Error::new(io::ErrorKind::Other, "No value for enum after $")) }, @@ -109,13 +109,25 @@ impl FromStr for Icon { } impl fmt::Display for Icon { + /// Output is a Enum kebab case with # separating base16 : separated values, _ if String value + /// + /// ``` + /// use cyme::icon::*; + /// + /// let icon: Icon = Icon::VidPid((0x1d50, 0x6018)); + /// assert_eq!(format!("{}", icon), "vid-pid#1d50:6018"); + /// + /// let icon: Icon = Icon::UnknownVendor; + /// assert_eq!(format!("{}", icon), "unknown-vendor"); + /// ``` + /// fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match self { Icon::Vid(v) => write!(f, "vid#{:04x}", v), Icon::VidPid((v, p)) => write!(f, "vid-pid#{:04x}:{:04x}", v, p), Icon::VidPidMsb((v, p)) => write!(f, "vid-pid-msb#{:04x}:{:02x}", v, p), Icon::Classifier(c) => write!(f, "classifier#{:02x}", c.to_owned() as u8), - Icon::ClassifierSubProtocol(c) => write!(f, "classifier-sub-protocol#{}:{}:{}", c.0.to_owned() as u8, c.1, c.2), + Icon::ClassifierSubProtocol(c) => write!(f, "classifier-sub-protocol#{:02x}:{:02x}:{:02x}", c.0.to_owned() as u8, c.1, c.2), Icon::Endpoint(Direction::In) => write!(f, "endpoint_in"), Icon::Endpoint(Direction::Out) => write!(f, "endpoint_out"), _ => { @@ -369,11 +381,29 @@ pub fn get_ascii_tree_icon(i: &Icon) -> String { ASCII_TREE.get(i).unwrap().to_string() } +/// Returns clone of lazy_static defaults +pub fn defaults() -> HashMap { + DEFAULT_ICONS.clone() +} + +/// Returns example list of icons with all [`Icon`] types +pub fn example() -> HashMap { + HashMap::from([ + (Icon::UnknownVendor, "\u{f287}".into()), // usb plug default  + (Icon::Vid(0x05ac), "\u{f179}".into()), // apple  + (Icon::VidPid((0x1d50, 0x6018)), "\u{f188}".into()), // black magic probe  + (Icon::VidPidMsb((0x0483, 0x37)), "\u{f188}".into()), // st-link  + (Icon::ClassifierSubProtocol((ClassCode::ApplicationSpecificInterface, 0x01, 0x01)), "\u{f188}".into()), // DFU  + (Icon::Vid(0x2e8a), "\u{f315}".into()), // raspberry pi foundation  + (Icon::Classifier(ClassCode::CDCCommunications), "\u{e795}".into()), // serial  + (Icon::UndefinedClassifier, "\u{2636}".into()), //☶ + ]) +} + #[cfg(test)] mod tests { use super::*; - // #[ignore] #[test] fn test_serialize_theme() { let theme = IconTheme{ @@ -399,13 +429,53 @@ mod tests { #[test] fn test_serialize_defaults() { - let theme = IconTheme{ - icons: Some(HashMap::from([ - (Icon::UnknownVendor, "\u{f287}".into()), // usb plug default  - // (Icon::Classifier(ClassCode::HID), "\u{f80b}".into()), //  - ])), - ..Default::default() - }; - println!("{}", serde_json::to_string(&theme).unwrap()); + serde_json::to_string(&defaults()).unwrap(); + } + + #[test] + fn test_serialize_example() { + println!("{}", serde_json::to_string_pretty(&example()).unwrap()); + } + + #[test] + fn test_deserialize_icon_tuples() { + let item: (Icon, &'static str) = (Icon::VidPid((0x1d50, 0x6018)), "\u{f188}".into()); + let item_ser = serde_json::to_string(&item).unwrap(); + assert_eq!(item_ser, r#"["vid-pid#1d50:6018",""]"#); + + let item: (Icon, &'static str) = (Icon::Endpoint(Direction::In), ">".into()); + let item_ser = serde_json::to_string(&item).unwrap(); + assert_eq!(item_ser, r#"["endpoint_in",">"]"#); + + let item: (Icon, &'static str) = (Icon::ClassifierSubProtocol((ClassCode::HID, 0x01, 0x0a)), "K".into()); + let item_ser = serde_json::to_string(&item).unwrap(); + assert_eq!(item_ser, r#"["classifier-sub-protocol#03:01:0a","K"]"#); + } + + #[test] + fn icon_from_str() { + let str = "vid#1d50"; + let icon = Icon::from_str(str); + assert_eq!(icon.unwrap(), Icon::Vid(7504)); + + let str = "vid-pid#1d50:6018"; + let icon = Icon::from_str(str); + assert_eq!(icon.unwrap(), Icon::VidPid((7504, 24600))); + + let str = "classifier#03"; + let icon = Icon::from_str(str); + assert_eq!(icon.unwrap(), Icon::Classifier(ClassCode::HID)); + + let str = "classifier-sub-protocol#03:01:0a"; + let icon = Icon::from_str(str); + assert_eq!(icon.unwrap(), Icon::ClassifierSubProtocol((ClassCode::HID, 01, 10))); + + let str = "endpoint_in"; + let icon = Icon::from_str(str); + assert_eq!(icon.unwrap(), Icon::Endpoint(Direction::In)); + + let str = "unknown-vendor"; + let icon = Icon::from_str(str); + assert_eq!(icon.unwrap(), Icon::UnknownVendor); } } diff --git a/src/main.rs b/src/main.rs index 359ce8aa..61763cf0 100644 --- a/src/main.rs +++ b/src/main.rs @@ -15,6 +15,7 @@ use clap::CommandFactory; #[cfg(feature = "cli_generate")] use clap_complete::shells::*; #[cfg(feature = "cli_generate")] +use cyme::icon::example; #[cfg(feature = "cli_generate")] use std::path::PathBuf; @@ -327,7 +328,10 @@ fn print_man() -> Result<(), Error> { let mut buffer: Vec = Default::default(); man.render(&mut buffer)?; - std::fs::write(PathBuf::from(outdir).join("cyme.1"), buffer)?; + std::fs::write(PathBuf::from(&outdir).join("cyme.1"), buffer)?; + + // TODO example config + std::fs::write(PathBuf::from(&outdir).join("cyme_example_config.json"), serde_json::to_string_pretty(&example()).unwrap())?; Ok(()) } diff --git a/src/usb.rs b/src/usb.rs index 3624c5a9..4d6d8b6e 100644 --- a/src/usb.rs +++ b/src/usb.rs @@ -69,10 +69,15 @@ pub enum ClassCode { Billboard, USBTypeCBridge, I3CDevice, + /// Trace debugging equipment Diagnostic, + /// This base class is defined for devices that are Wireless controllers. Values not shown in the table below are reserved. These class codes are to be used in Interface Descriptors, with the exception of the Bluetooth class code which can also be used in a Device Descriptor WirelessController, + /// This base class is defined for miscellaneous device definitions. Some matching SubClass and Protocols are defined on the USB-IF website Miscellaneous, + /// This base class is defined for devices that conform to several class specifications found on the USB-IF website ApplicationSpecificInterface, + /// This base class is defined for vendors to use as they please VendorSpecificClass, } @@ -148,6 +153,7 @@ impl Into for ClassCode { } } +// TODO return device based on base class and subclass, protocol impl ClassCode { /// How the ClassCode is used [`DescriptorUsage`] pub fn usage(&self) -> DescriptorUsage { diff --git a/tests/integration_test.rs b/tests/integration_test.rs index 05198570..14c25ac7 100644 --- a/tests/integration_test.rs +++ b/tests/integration_test.rs @@ -1,5 +1,6 @@ mod common; +#[ignore] #[test] fn test_json_round_trip() { let te = common::TestEnv::new();